Я часто хотел попробовать это. Я бы создал шаблон ItemsControl для PropertyInfo.
Я создал тестовый класс:
public class MyClass
{
public string PropertyTest1 {get;set;}
public string PropertyTest2 { get; set; }
public string PropertyTest3 { get; set; }
public string PropertyTest4 { get; set; }
}
Чтобы отобразить свойства. В моем контексте данных для отображения у меня есть две вещи, к которым нужно привязать. Список PropertyInfos и объект, о котором идет речь. Поскольку PropertyInfo является статическим, вы могли бы быть в состоянии сделать это лучший способ, используя конвертер или что-то, и не нужно привязать его к свойству:
public PropertyInfo[] Properties
{
get { return typeof(MyClass).GetProperties(); }
}
public MyClass MyObject
{
get { return new MyClass { PropertyTest1 = "test", PropertyTest3 = "Some string", PropertyTest4 = "Last Property" }; }
}
Теперь, отображающая свойства легко:
<ItemsControl x:Name="PropertyDisplay" ItemsSource="{Binding Properties}" Grid.IsSharedSizeScope="True">
<ItemsControl.Resources>
<local:PropertyInfoValueConverter x:Key="PropertyInfoValueConverter"/>
</ItemsControl.Resources>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" Margin="4,2"/>
<TextBlock Grid.Column="1" Margin="4,2"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Но они являются «статическими», мы не можем привязываться к каким-либо значениям. Способ обойти это использовать свойство Tag, и мульти-связывающим преобразователь:
Так давайте добавим Tag="{Binding MyObject}"
к нашему ItemsSource, и бросить, что и в PropertyInfo в преобразователе значение для нашего второго TextBlock:
<TextBlock Grid.Column="1" Margin="4,2">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource PropertyInfoValueConverter}">
<Binding Path=""/>
<Binding ElementName="PropertyDisplay" Path="Tag"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
преобразователь на самом деле довольно просто, тем более, что вы не используете текстовые окна (так будет только для чтения только направление):
public class PropertyInfoValueConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
PropertyInfo propertyInfo = values[0] as PropertyInfo;
return propertyInfo.GetValue(values[1]);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Это результат:
Вы говорите, что вы хотите пространства для имен, которые можно было бы сделать с помощью преобразователя с некоторыми логики ищет любые правила именования у вас есть (пробелы перед заглавными буквами?).
Было бы здорово играть с помощью селекторов шаблонов, чтобы выбрать логические, строковые, плавающие шаблоны и относиться к ним по-разному. (Флажки, текст, 00.00 форматированный текст и т.д.)
Edit: Изучение шаблонов Selector
Вот Селектор пример шаблона:
public class PropertyInfoTemplateSelector : DataTemplateSelector
{
public DataTemplate StringTemplate { get; set; }
public DataTemplate IntegerTemplate { get; set; }
public DataTemplate DecimalTemplate { get; set; }
public DataTemplate BooleanTemplate { get; set; }
public DataTemplate DefaultTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
PropertyInfo propertyInfo = item as PropertyInfo;
if (propertyInfo.PropertyType == typeof(string))
{
return StringTemplate;
}
else if (propertyInfo.PropertyType == typeof(int))
{
return IntegerTemplate;
}
else if (propertyInfo.PropertyType == typeof(float) || propertyInfo.PropertyType == typeof(double))
{
return DecimalTemplate;
}
else if (propertyInfo.PropertyType == typeof(bool))
{
return BooleanTemplate;
}
return DefaultTemplate;
}
}
Наша ItemsControl теперь просто:
<ItemsControl x:Name="PropertyDisplay" ItemsSource="{Binding Properties}"
Grid.IsSharedSizeScope="True"
Tag="{Binding MyObject}"
ItemTemplateSelector="{StaticResource PropertyInfoTemplateSelector}"
Margin="20"/>
Я также добавил пространства в названиях, использующих этот преобразователь:
public class PropertyInfoNameConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string text = value as string;
if (string.IsNullOrWhiteSpace(text))
return string.Empty;
StringBuilder newText = new StringBuilder(text.Length * 2);
newText.Append(text[0]);
for (int i = 1; i < text.Length; i++)
{
if (char.IsUpper(text[i]))
if ((text[i - 1] != ' ' && !char.IsUpper(text[i - 1])) ||
(char.IsUpper(text[i - 1]) &&
i < text.Length - 1 && !char.IsUpper(text[i + 1])))
newText.Append(' ');
newText.Append(text[i]);
}
return newText.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
(Задолженность: https://stackoverflow.com/a/272929/1305699).
Обновление нашего класса содержит некоторые логические и fload поля:
очень хороший! Благодарю. – tjcertified