如何仅在布局的一部分上使用 WPF DataTemplates
How to use WPF DataTemplates only on a part of the layout
在 MVVM 环境中,我使用列表框以不同的方式可视化不同的数据类型,但有一些共同的样式元素。最小示例如下所示:
interface IPropertyItem
{
string Description { get; }
}
class PropertyBoolItem : IPropertyItem
{
public string Description { get; }
public bool Value { get; set; }
}
class PropertyStringItem : IPropertyItem
{
public string Description { get; }
public string DifferentValue { get; set; }
}
<ListBox>
<ListBox.Resources>
<!-- A bool item -->
<DataTemplate DataType="{x:Type types:PropertyBoolItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="130"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text{Binding Description}/>
<CheckBox Grid.Column="3" IsChecked="{Binding Value}"/>
</Grid>
</DataTemplate>
<!-- A string item -->
<DataTemplate DataType="{x:Type types:PropertyStringItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="130"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text{Binding Description}/>
<TextBox Grid.Column="3" Text="{Binding DifferentValue, Mode=TwoWay}"/>
</Grid>
</DataTemplate>
<!-- and so on... -->
</ListBox.Resources>
</ListBox>
目前一切正常。但我想知道是否有一种 更优雅 的方式来实现这一点,因为标记的大部分总是相同的,只有一些部分(如复选框或文本框)依赖于数据类型。
提前致谢!
不确定这是否符合 "more elegant",但它更小 XAML,而且您不必为复杂的 ListBoxItem 模板操心。
<ListBox ...>
<ListBox.Resources>
<!-- A bool item -->
<DataTemplate DataType="{x:Type types:PropertyBoolItem}">
<CheckBox IsChecked="{Binding Value}"/>
</DataTemplate>
<!-- A string item -->
<DataTemplate DataType="{x:Type types:PropertyStringItem}">
<TextBox Text="{Binding DifferentValue}"/>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="130"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Description}"/>
<ContentPresenter Grid.Column="3" Content="{Binding}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
在 MVVM 环境中,我使用列表框以不同的方式可视化不同的数据类型,但有一些共同的样式元素。最小示例如下所示:
interface IPropertyItem
{
string Description { get; }
}
class PropertyBoolItem : IPropertyItem
{
public string Description { get; }
public bool Value { get; set; }
}
class PropertyStringItem : IPropertyItem
{
public string Description { get; }
public string DifferentValue { get; set; }
}
<ListBox>
<ListBox.Resources>
<!-- A bool item -->
<DataTemplate DataType="{x:Type types:PropertyBoolItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="130"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text{Binding Description}/>
<CheckBox Grid.Column="3" IsChecked="{Binding Value}"/>
</Grid>
</DataTemplate>
<!-- A string item -->
<DataTemplate DataType="{x:Type types:PropertyStringItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="130"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text{Binding Description}/>
<TextBox Grid.Column="3" Text="{Binding DifferentValue, Mode=TwoWay}"/>
</Grid>
</DataTemplate>
<!-- and so on... -->
</ListBox.Resources>
</ListBox>
目前一切正常。但我想知道是否有一种 更优雅 的方式来实现这一点,因为标记的大部分总是相同的,只有一些部分(如复选框或文本框)依赖于数据类型。
提前致谢!
不确定这是否符合 "more elegant",但它更小 XAML,而且您不必为复杂的 ListBoxItem 模板操心。
<ListBox ...>
<ListBox.Resources>
<!-- A bool item -->
<DataTemplate DataType="{x:Type types:PropertyBoolItem}">
<CheckBox IsChecked="{Binding Value}"/>
</DataTemplate>
<!-- A string item -->
<DataTemplate DataType="{x:Type types:PropertyStringItem}">
<TextBox Text="{Binding DifferentValue}"/>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="130"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Description}"/>
<ContentPresenter Grid.Column="3" Content="{Binding}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>