В вашем вопросе много, казалось бы, не относящейся к делу информации, которая, как мне кажется, действительно касается механизмов создания управляемых метаданными пользовательских интерфейсов в WPF.Вот способ решения этой проблемы:
Предположим, что вы хотите создать пользовательский интерфейс, похожий на лист свойств: сетка, отображающая строку для каждого свойства, с подсказкой и элементом управления вводом некоторого вида.Для этого вам понадобится коллекция объектов, каждый элемент которой содержит свойства, которые описывают свойство и его значение.Простой дизайн - это класс, который предоставляет свойство Prompt
и свойство Value
и реализует уведомление об изменении.
После создания и заполнения этой коллекции вы можете реализовать ItemsControl
, отображающийэто в сетке:
<ItemsControl ItemsSource="{Binding Properties}" Grid.IsSharedSizeScope="True">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="PropertyViewModel">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Prompt"/>
<ColumnDefinition SharedSizeGroup="Value"/>
</Grid.ColumnDefinition>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
</Grid>
<Label Content="{Binding Prompt}"/>
<TextBox Grid.Column="1" Text="{Binding Value, Mode=TwoWay}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Это довольно просто - самое сложное в этом заключается в использовании Grid.IsSharedSizeScope
, чтобы все сетки, создаваемые этим элементом управления, использовали одинаковую ширину столбцов.Вы также можете использовать ListView
вместо ItemsControl
, хотя использование ListView
для этого создает кучу проблем, связанных с фокусом и выбором, с которыми вам, возможно, не захочется иметь дело.
Обратите внимание, что, посколькуиз магии, связанной с сопоставлением шаблонов WPF, вы могли бы реализовать свойство Value
как object
и создавать различные шаблоны для обработки различных возможных типов свойства Value
- так же, как это делает лист реальной собственности.Для этого вы должны создать шаблон для каждого типа, например:
<DataTemplate DataType="{x:Type System:String}">
<TextBox Text="{Binding Value, Mode=TwoWay}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type System:DateTime}">
<DatePicker Value="{Binding Value, Mode=TwoWay}"/>
</DataTemplate>
и т. Д.Затем вы измените шаблон для PropertyViewModel
, чтобы вместо отображения Value
в TextBox
он использовал ContentPresenter
, например:
<ContentPresenter Grid.Column="1" Content="{Binding}"/>