Вы хотите, чтобы элемент управления, имеющий метку с именем свойства и элемент управления, редактировали значение свойства, поэтому начните с создания класса, который обернет свойство определенного объекта, чтобы действовать как 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); }
}
}
Вы хотите связать ItemsSource объекта ListBox с объектом, чтобы заполнить его этими элементами управления, поэтому создайте 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}}"/>