MenuItemsControl使用项的派生类型

时间:2015-06-04 18:37:36

标签: c# wpf

我有一个从MenuItem派生的类型。我希望在从MenuItem.ItemsSource生成子菜单项时使用该类型。

这是一个XAML示例,它创建一个正确类型的项目,但将其包装在另一个MenuItem中。我想摆脱包装MenuItem。

    <MenuItem ItemsSource="{Binding MyItems}">
        <MenuItem.ItemTemplate>
            <DataTemplate>
                <local:MenuItemDerived Header="{Binding Name}" Property1="{Binding Prop1}" />
            </DataTemplate>
        </MenuItem.ItemTemplate>
    </MenuItem>

我可以将生成的子类型更改为派生类型吗?

1 个答案:

答案 0 :(得分:2)

通常,您只需要覆盖MenuItem控件模板来创建自定义项而不是子类化MenuItem。但是,可以执行您要求的操作并更改生成的子菜单项的类型。根据您的使用情况,有两种方法可以执行此操作。

  1. 为菜单中的每种项目设置ItemContainerTemplate。假设您使用名为MyItem的类的实例填充它,您将执行此操作:

    <MenuItem Header="Test" UsesItemContainerTemplate="True" ItemsSource="{Binding Items}">
        <MenuItem.Resources>
            <ItemContainerTemplate
                DataType="{x:Type local:MyItem}">
                <local:MenuItemDerived />
            </ItemContainerTemplate>
        </MenuItem.Resources>
    </MenuItem>
    

    您可以根据需要添加任意数量,可以在菜单中添加每种类型的项目(通常只有一种)。

  2. 使用ItemContainerTemplateSelector使用您要选择模板的任何自定义逻辑。如果您只是希望每个生成的项目都使用相同的菜单项类型,这是很好的,因为第一个选项不允许这样做(您不能使用Object作为数据模板的数据类型)。如果您希望将模板选择基于自定义逻辑,这比检查项目类型更复杂,也是必要的。

    <MenuItem Header="Test" UsesItemContainerTemplate="True" ItemsSource="{Binding Items}">
        <MenuItem.ItemContainerTemplateSelector>
            <local:MenuItemContainerTemplateSelector>
                <DataTemplate>
                    <local:MenuItemDerived />
                </DataTemplate>
            </local:MenuItemContainerTemplateSelector>
        </MenuItem.ItemContainerTemplateSelector>
    </MenuItem>
    

    我在那里使用的非常简单的MenuItemContainerTemplateSelector类看起来像这样:

    [ContentProperty("Template")]
    internal class MenuItemContainerTemplateSelector : ItemContainerTemplateSelector
    {
        public DataTemplate Template { get; set; }
    
        public override DataTemplate SelectTemplate(object item, ItemsControl parentItemsControl)
        {
            return Template;
        }
    }
    

    当然,如果您愿意,您可以制作一个包含多个模板的复杂选择器。

  3. 请注意两种情况下UsesItemContainerTemplate属性的用法。任何自定义项容器模板都可以使用。