Automatic Data Template Selection
Move the data templates to the ItemsControl
resources and assign a DataType
.
<StackPanel>
<!--Items Control containing all list of properties to be shown-->
<ItemsControl x:Name="Local" ItemsSource="{Binding Properties}" Background="White">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type local:StringValuePropertyItemVM}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Label Content="{Binding Label}"
IsEnabled="{Binding IsEnabled}"
Grid.Column="0"/>
<!-- Here based on type need to change the TextBox with ComboBox-->
<TextBox Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Grid.Column="1"
IsEnabled="{Binding IsEnabled}"/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type local:ComboBoxPropertyItemVM}">
<ComboBox/>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
</StackPanel>
The ItemsControl
will automatically select the right data template based on the type.
Data Template Selector
Although you do not need it in this case, for more complex cases (e.g. conditions based on the view model), you could implement a DataTemplateSelector
, like this:
public class PropertyDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (!(container is FrameworkElement frameworkElement))
return null;
switch (item)
{
case StringValuePropertyItemVM _:
return (DataTemplate)frameworkElement.FindResource("StringValuePropertyItemVMDataTemplate");
case ComboBoxPropertyItemVM _:
return (DataTemplate)frameworkElement.FindResource("ComboBoxPropertyItemVMDataTemplate");
default:
return null;
}
}
}
Then you would define the data templates in a resource dictionary in scope with keys.
<DataTemplate x:Key="StringValuePropertyItemVMDataTemplate" DataType="{x:Type local:StringValuePropertyItemVM}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Label Content="{Binding Label}"
IsEnabled="{Binding IsEnabled}"
Grid.Column="0"/>
<!-- Here based on type need to change the TextBox with ComboBox-->
<TextBox Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Grid.Column="1"
IsEnabled="{Binding IsEnabled}"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="ComboBoxPropertyItemVMDataTemplate" DataType="{x:Type local:ComboBoxPropertyItemVM}">
<ComboBox/>
</DataTemplate>
Finally, you would assign or reference an instance of the selector to the ItemsControl
.
<StackPanel>
<!--Items Control containing all list of properties to be shown-->
<ItemsControl x:Name="Local" ItemsSource="{Binding Properties}" Background="White">
<ItemsControl.ItemTemplateSelector>
<local:PropertyDataTemplateSelector/>
</ItemsControl.ItemTemplateSelector>
</ItemsControl>
</StackPanel>
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…