基于枚举为数据模板选择用户控件

Selecting User Control for Data Template based on an Enum

我正在开发一个 WPF 应用程序,目前我有一个 ItemsControl 绑定到我的视图模型 ObservableCollection 并且我有一个 DataTemplate 使用 UserControlcanvas 上呈现项目。您可以使用多个用户控件,然后根据 Enum 切换使用哪个吗?另一种查看方式是根据 EnumObservableCollection 中的项目创建 ButtonTextBox

您可以 select 使用自定义项的数据模板 DataTemplateSelector。假设我们有以下内容:

public enum Kind
{
    Button, TextBox,
}

public class Data
{
    public Kind Kind { get; set; }
    public string Value { get; set; }
}

您的数据模板select或者可能看起来像这样:

public class MyTemplateSelector : DataTemplateSelector
{
    public DataTemplate ButtonTemplate { get; set; }

    public DataTemplate TextBoxTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        Data data = (Data)item;
        switch (data.Kind)
        {
            case Kind.Button:
                return ButtonTemplate;
            case Kind.TextBox:
                return TextBoxTemplate;
        }

        return base.SelectTemplate(item, container);
    }
}

在 XAML 中,为您要涵盖的所有情况声明模板,在本例中为按钮和文本框:

<Window.Resources>
    <ResourceDictionary>
        <DataTemplate x:Key="ButtonTemplate" DataType="local:Data">
            <Button Content="{Binding Value}" />
        </DataTemplate>
        <DataTemplate x:Key="TextBoxTemplate" DataType="local:Data">
            <TextBox Text="{Binding Value}" />
        </DataTemplate>
    </ResourceDictionary>
</Window.Resources>

最后,让您的 ItemsControl 创建自定义模板的实例 select 或者,从上述数据模板初始化它的两个 DataTemplate 属性:

<ItemsControl>
    <ItemsControl.ItemTemplateSelector>
        <local:MyTemplateSelector
            ButtonTemplate="{StaticResource ButtonTemplate}"
            TextBoxTemplate="{StaticResource TextBoxTemplate}"/>
    </ItemsControl.ItemTemplateSelector>
    <ItemsControl.Items>
        <local:Data Kind="Button" Value="1. Button" />
        <local:Data Kind="TextBox" Value="2. TextBox" />
        <local:Data Kind="TextBox" Value="3. TextBox" />
        <local:Data Kind="Button" Value="4. Button" />
    </ItemsControl.Items>
</ItemsControl>

(在现实生活中,设置 ItemsSource 而不是像我那样声明内联项。)

为了完整性:要访问您的 C# 类,您需要设置命名空间,例如,

xmlns:local="clr-namespace:WPF"

另一个可能的快速解决方案是使用数据触发器:

        <ContentControl>
            <ContentControl.Style>
                <Style TargetType="ContentControl">
                    <Setter Property="Content"
                            Value="{StaticResource YourDefaultLayout}" />
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding YourEnumVMProperty}"
                                     Value="{x:Static local:YourEnum.EnumValue1}">
                            <Setter Property="Content"
                                    Value="{StaticResource ContentForEnumValue1}" />
                        </DataTrigger>
                        <DataTrigger Binding="{Binding YourEnumVMProperty}"
                                     Value="{x:Static local:YourEnum.EnumValue2}">
                            <Setter Property="Content"
                                    Value="{StaticResource ContentForEnumValue2}" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ContentControl.Style>
        </ContentControl>

您还可以使用触发器定义整个控件的模板setter。

我更喜欢这个,因为不需要定义所有的 DataTemplateSelector 东西等