我有一组存储在CollectionViewSource
中并绑定到DataGrid
的对象。 我想显示DataGrid
中当前所选对象的“详情视图”。我可以使用CollectionViewSource.View.CurrentItem
获取当前对象。
MyClass
{
[IsImportant]
AProperty{}
AnotherProperty{}
[IsImportant]
YetAnotherProperty{}
}
我想要做的是在列表框中显示标签(带有属性名称)和控件(用于编辑),每个属性都标有IsImportant
属性。绑定必须在所做的编辑,DataGrid和后备对象之间起作用。显示的控件应根据属性的类型而有所不同,可以是boolean
,string
或IEnumerable<string>
(我已编写IValueConverter
以在可枚举和换行符分隔之间进行转换字符串)。
有谁知道实现此目的的方法?我现在可以通过以下方式显示每个属性的值,但编辑它们不会更新后备对象:
listBox.ItemsSource = from p in typeof(MyClass).GetProperties()
where p.IsDefined(typeof(IsImportant), false)
select p.GetValue(_collectionViewSource.View.CurrentItem, null);
为了澄清,我希望这可以'自动'发生,而无需在XAML中手动指定属性名称。如果我可以在运行时基于哪些属性标记属性动态添加到XAML ,那也没关系。
答案 0 :(得分:12)
您希望具有带属性名称和控件的标签的控件编辑属性值,因此首先创建一个包装特定对象的属性的类,以充当该控件的DataContext:
public class PropertyValue
{
private PropertyInfo propertyInfo;
private object baseObject;
public PropertyValue(PropertyInfo propertyInfo, object baseObject)
{
this.propertyInfo = propertyInfo;
this.baseObject = baseObject;
}
public string Name { get { return propertyInfo.Name; } }
public Type PropertyType { get { return propertyInfo.PropertyType; } }
public object Value
{
get { return propertyInfo.GetValue(baseObject, null); }
set { propertyInfo.SetValue(baseObject, value, null); }
}
}
您希望将ListBox的ItemsSource绑定到对象以使用这些控件填充它,因此创建一个IValueConverter,它将对象转换为PropertyValue对象的列表以获取其重要属性:
public class PropertyValueConverter
: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return
from p in value.GetType().GetProperties()
where p.IsDefined(typeof(IsImportant), false)
select new PropertyValue(p, value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
}
最后一个技巧是你希望编辑控件根据属性的类型而变化。您可以通过使用ContentControl并根据属性类型将ContentTemplate设置为各种编辑器模板之一来实现。如果属性是布尔值,则此示例使用CheckBox,否则使用TextBox:
<DataTemplate x:Key="CheckBoxTemplate">
<CheckBox IsChecked="{Binding Value}"/>
</DataTemplate>
<DataTemplate x:Key="TextBoxTemplate">
<TextBox Text="{Binding Value}"/>
</DataTemplate>
<Style x:Key="EditControlStyle" TargetType="ContentControl">
<Setter Property="ContentTemplate" Value="{StaticResource TextBoxTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding PropertyType}" Value="{x:Type sys:Boolean}">
<Setter Property="ContentTemplate" Value="{StaticResource CheckBoxTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>
<DataTemplate DataType="{x:Type local:PropertyValue}">
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Name}"/>
<ContentControl Style="{StaticResource EditControlStyle}" Content="{Binding}"/>
</StackPanel>
</DataTemplate>
然后,您可以将ListBox创建为:
<ItemsControl ItemsSource="{Binding Converter={StaticResource PropertyValueConverter}}"/>