如何正确地将ViewModel(包括分隔符)绑定到WPF的菜单? [英] How to correctly bind a ViewModel (which Include Separators) to WPF's Menu?

查看:107
本文介绍了如何正确地将ViewModel(包括分隔符)绑定到WPF的菜单?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用MVVM,我想将MenuViewModels的列表数据绑定到我的maim菜单.其中由一组菜单项和分隔符组成.

I'm using MVVM and I want to data bind my list of MenuViewModels to my maim menu. Which consists of a set of menu items and separators.

这是我的MenuItemViewModel代码:

Here's my MenuItemViewModel code:

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(取决于我尝试过的内容).

Should be very simple stuff. Unfortunately, either the menu item looks wrong or the separator is an empty menuItem (depending on what I've tried).

那么,如何获取我的Menu来找到我的两个DataTemplates?

So, how do I get my Menu to find my two DataTemplates?

推荐答案

解决了我自己的问题

花了几个小时在网络上搜索之后,我发现了许多实例,这些实例对WPF的本意是有效的,而对WPF却毫无用处.

After spending several hours searching the web, I found lots of examples that work against the WPF's natural intentions but none that worked with it.

这里是与控件配合使用而不是与Menu控件配合使用的方法...

Here's how to work with the Menu control and not against it...

背景知识

WPF的Menu控件通常会 使用ItemsSource属性为您自动创建MenuItem对象,方法是将其绑定到POCO集合.

WPF's Menu control will normally auto create MenuItem objects for you when it is binded to a POCO collection, using the ItemsSource property.

但是,可以覆盖此默认行为 !这就是...

However, this default behavior can be overridden! Here's how...

解决方案

首先,您必须创建一个从ItemContainerTemplateSelector派生的类.或使用我创建的简单类:

First, you must create a class that derives from ItemContainerTemplateSelector. Or use the simple class I've created:

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 resources对象,如下所示:

Second, you must add a reference to the MenuItemContainerTemplateSelector class to your Windows resources object, like so:

<Window.Resources>
    <Selectors:MenuItemContainerTemplateSelector x:Key="_menuItemContainerTemplateSelector" />

第三,必须同时在MenuMenuItem(在HierarchicalDataTemplate中定义)上设置两个属性(UsesItemContainerTemplateItemContainerTemplateSelector).

Third, you must set two properties (UsesItemContainerTemplate, and ItemContainerTemplateSelector) on both the Menu and the MenuItem (which is defined in the HierarchicalDataTemplate).

像这样:

    <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会按预期工作.

For optimization purposes, the Menu uses the UsesItemContainerTemplate flag (which has a default value of false) to skip the DataTemplate lookup and just returns a normal MenuItem object. Therefore, we needed to set this value to true and then our ItemContainerTemplateSelector works as expected.

快乐编码!

这篇关于如何正确地将ViewModel(包括分隔符)绑定到WPF的菜单?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆