2016-11-06 13 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,則不需要這樣做。

相關問題