我创建了一个带有 ListControl 的自定义 UserControl。
<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>
我还在这个自定义 UserControl 中创建了一个 DependencyProperty,并将 ListControl 的 ItemsSource 绑定(bind)到这个 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 的名称来将它们的文本值绑定(bind)到属性。
<TextBlock Text="{Binding "????????"}"/>
<TextBlock Text="{Binding "????????"}"/>
而不是“????????”我想动态设置此属性的名称 - 通过自定义 UserControl 中的自定义字符串属性。
[这不是工作代码,我删除了不需要的部分以使其更具可读性]
您可以使用一个简单的多值转换器来做到这一点:
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>
这是我测试过的一个简单的 View 模型:
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。
我是一名优秀的程序员,十分优秀!