如何仅在布局的一部分上使用 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>