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

时间:2016-02-01 21:45:49

标签: wpf data-binding datatemplate

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

2 个答案:

答案 0 :(得分:4)

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

public enum Kind
{
    Button, TextBox,
}

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

您的数据模板选择器可能如下所示:

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创建自定义模板选择器的实例,从以上数据模板初始化其两个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"

答案 1 :(得分:0)

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

        <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>

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

我之所以这样,是因为不需要定义所有DataTemplateSelector之类的东西。