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

7

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


我理解的是否正确,您想根据Enum值而不是ViewModel来更改您的UserControl - StepUp
2个回答

10

您可以使用自定义的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
非常棒的回复,真的很有帮助。我已经通过使用UserControls使其正常工作了,这也是我的最终目标,非常感谢。 - Grenter

1
另一种可能的快速解决方案是使用数据触发器:
<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等内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接