我有一个从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>
我可以将生成的子类型更改为派生类型吗?
答案 0 :(得分:2)
通常,您只需要覆盖MenuItem控件模板来创建自定义项而不是子类化MenuItem。但是,可以执行您要求的操作并更改生成的子菜单项的类型。根据您的使用情况,有两种方法可以执行此操作。
为菜单中的每种项目设置ItemContainerTemplate
。假设您使用名为MyItem
的类的实例填充它,您将执行此操作:
<MenuItem Header="Test" UsesItemContainerTemplate="True" ItemsSource="{Binding Items}">
<MenuItem.Resources>
<ItemContainerTemplate
DataType="{x:Type local:MyItem}">
<local:MenuItemDerived />
</ItemContainerTemplate>
</MenuItem.Resources>
</MenuItem>
您可以根据需要添加任意数量,可以在菜单中添加每种类型的项目(通常只有一种)。
使用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;
}
}
当然,如果您愿意,您可以制作一个包含多个模板的复杂选择器。
请注意两种情况下UsesItemContainerTemplate
属性的用法。任何自定义项容器模板都可以使用。