我正在使用MVVM,我希望将我的Menuviewmodel列表数据绑定到我的maim菜单.其中包含一组菜单项和分隔符.
public interface IMenuItemviewmodel { } [DebuggerDisplay("---")] public class Separatorviewmodel : IMenuItemviewmodel { } [DebuggerDisplay("{Header},Children={Children.Count}")] public class MenuItemviewmodel : IMenuItemviewmodel,INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public MenuItemviewmodel(string header,ICommand command,ImageSource imageSource) { Header = header; Command = command; ImageSource = imageSource; Children = new List<IMenuItemviewmodel>(); } public string Header { get; private set; } public ICommand Command { get; private set; } public ImageSource ImageSource { get; private set; } public IList<IMenuItemviewmodel> Children { get; private set; } }
我的主窗口看起来像这样:
<Window.Resources> <HierarchicalDataTemplate DataType="{x:Type viewmodel:MenuItemviewmodel}" ItemsSource="{Binding Children}"> <MenuItem Header="{Binding Header}" Command="{Binding Command}"/> </HierarchicalDataTemplate> <DataTemplate DataType="{x:Type viewmodel:Separatorviewmodel}"> <Separator /> </DataTemplate> </Window.Resources> <DockPanel> <Menu DockPanel.Dock="Top" ItemsSource="{Binding MenuItems}"> </Menu> </DockPanel>
应该是非常简单的东西.不幸的是,菜单项看起来不对或者分隔符是一个空的menuItem(取决于我尝试过的).
那么,如何让我的菜单找到我的两个DataTemplates?
解决方法
解决了我自己的问题
在花了几个小时搜索网络后,我发现很多例子都违背了WPF的自然意图,但没有一个能够解决这个问题.
以下是如何使用Menu控件而不是它…
一点背景
WPF的Menu控件通常会在使用ItemsSource属性绑定到POCO集合时自动为您创建MenuItem对象.
但是,可以覆盖此默认行为!这是如何做…
解决方案
首先,您必须创建一个派生自ItemContainerTemplateSelector的类.或者使用我创建的简单类:
public class MenuItemContainerTemplateSelector : ItemContainerTemplateSelector { public override DataTemplate SelectTemplate(object item,ItemsControl parentItemsControl) { var key = new DataTemplateKey(item.GetType()); return (DataTemplate) parentItemsControl.FindResource(key); } }
其次,您必须将MenuItemContainerTemplateSelector类的引用添加到Windows资源对象,如下所示:
<Window.Resources> <Selectors:MenuItemContainerTemplateSelector x:Key="_menuItemContainerTemplateSelector" />
第三,必须在Menu和MenuItem(在HierarchicalDataTemplate中定义)上设置两个属性(UsesItemContainerTemplate和ItemContainerTemplateSelector).
像这样:
<HierarchicalDataTemplate DataType="{x:Type viewmodel:MenuItemviewmodel}" ItemsSource="{Binding Children}"> <MenuItem Header="{Binding Header}" Command="{Binding Command}" UsesItemContainerTemplate ="true" ItemContainerTemplateSelector= "{StaticResource _menuItemContainerTemplateSelector}"/> </HierarchicalDataTemplate> <Menu DockPanel.Dock="Top" ItemsSource="{Binding MenuItems}" UsesItemContainerTemplate="True" ItemContainerTemplateSelector= "{StaticResource _menuItemContainerTemplateSelector}"> </Menu>
为什么会这样
出于优化目的,Menu使用UsesItemContainerTemplate标志(其默认值为false)跳过DataTemplate查找并返回正常的MenuItem对象.因此,我们需要将此值设置为true,然后我们的ItemContainerTemplateSelector按预期工作.
快乐的编码!