2016-11-06 22 views
2

我创建了一个具有ListControl的自定义UserControl。XAML:如何将元素绑定到属性名称是动态的,可以在不同的地方有不同的名称

<UserControl> 
    <UserControl.Resources> 
     <Style TargetType="ItemsControl"> 
      <Setter Property="ItemTemplate"> 
       <Setter.Value> 
        <DataTemplate> 
         <simple:TrackItem />       
        </DataTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </UserControl.Resources> 
    <ItemsControl ItemsSource="{Binding ElementName=Root, Path=ItemsSource}"/> 
</UserControl> 

我也创建这个自定义用户控件一个DependencyProperty并绑定列表控件的的ItemsSource这个的DependencyProperty。

public partial class TracksList : UserControl 
    { 
     public TracksList() 
     { 
      InitializeComponent(); 
     } 

     public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(
      "ItemsSource", typeof(IEnumerable), typeof(TracksList), new FrameworkPropertyMetadata(default(IEnumerable))); 

     public IEnumerable ItemsSource 
     { 
      get { return (IEnumerable) GetValue(ItemsSourceProperty); } 
      set { SetValue(ItemsSourceProperty, value); } 
     } 

    } 

我覆盖ItemsControl的ItemTemplate。这个ItemTemplate有两个TextBlock元素,所以这个TextBlocks需要项目DataType的名字来将他们的Text值绑定到属性。

<TextBlock Text="{Binding "????????"}"/> 
    <TextBlock Text="{Binding "????????"}"/> 

而不是“???????”我想动态地设置此属性的名称 - 通过自定义UserControl中的自定义字符串Property。

[这是不工作的代码,我删除不需要的部分,使其更具有可读性]

+0

你可以在你打算绑定什么的基础上增加一些细节?还有一点关于项目模板中有什么的代码等 –

+0

IEnumerable数据类型它有点模糊,因此,很难从它获得特定的位置。你能告诉使用你将绑定到“ItemsSource”的数据类型吗? –

+0

是否要在ItemsSource中显示每个项目的*每个属性?或者只是一些属性?你的代码将如何决定要显示哪些属性? –

回答

0

可以用一个简单的多值转换器做到这一点:

public class NamedPropertyValueConverter : IMultiValueConverter 
{ 
    public object Convert(
     object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     var sourceObj = values[0]; 
     var propName = values[1].ToString(); 

     var propInfo = sourceObj.GetType().GetProperty(propName); 

     return propInfo.GetValue(sourceObj); 
    } 

    public object[] ConvertBack(
     object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

例XAML:

<Window.DataContext> 
    <local:ViewModel /> 
</Window.DataContext> 
<Window.Resources> 
    <local:NamedPropertyValueConverter x:Key="NamedPropertyValue" /> 
</Window.Resources> 
<Grid> 
    <StackPanel Orientation="Vertical" > 
     <TextBox Text="{Binding Foo, UpdateSourceTrigger=PropertyChanged}" /> 
     <TextBlock> 
      <TextBlock.Text> 
       <MultiBinding Converter="{StaticResource NamedPropertyValue}"> 
        <Binding /> 
        <Binding Path="PropertyNameProp" /> 
       </MultiBinding> 
      </TextBlock.Text> 
     </TextBlock> 
    </StackPanel> 
</Grid> 

而这里的,我测试了一个简单的视图模型与:

public class ViewModel : ViewModelBase 
{ 
    #region Foo Property 
    private String _foo = "Initial value of Foo"; 
    public String Foo 
    { 
     get { return _foo; } 
     set 
     { 
      if (value != _foo) 
      { 
       _foo = value; 
       OnPropertyChanged(); 
       OnPropertyChanged(nameof(PropertyNameProp)); 
       // This works too, but all properties will be requeried. 
       // In some cases that may be too expensive. 
       //OnPropertyChanged(null); 
      } 
     } 
    } 
    #endregion Foo Property 

    #region PropertyNameProp Property 
    private String _propertyNameProp = "Foo"; 
    public String PropertyNameProp 
    { 
     get { return _propertyNameProp; } 
     set 
     { 
      if (value != _propertyNameProp) 
      { 
       _propertyNameProp = value; 
       OnPropertyChanged(); 
      } 
     } 
    } 
    #endregion PropertyNameProp Property 
} 

请注意,Foo必须在其值改变时调用OnPropertyChanged(nameof(PropertyNameProp))。否则,Binding将不知道任何更改,并且不会更新,因为Binding不知道Foo存在。

如果您想为此转换器实现ConvertBack,您需要重新考虑一些事情,但如果您将值设置为TextBlock s,则不需要这样做。

相关问题