使用DataTemplate进行动态菜单时,为什么热键不起作用?

时间:2017-05-23 09:52:14

标签: wpf xaml datatemplate

我可以将自己类型的集合绑定到菜单中。但我正在与热键挣扎。热键显示但不起作用或热键不显示但工作正常。

你知道这里出了什么问题吗?

以下是精简代码:

    public class Category : DependencyObject
{
    public string Caption
    {
        get { return (string)GetValue(CaptionProperty); }
        set { SetValue(CaptionProperty, value); }
    }
    public static readonly DependencyProperty CaptionProperty =
        DependencyProperty.Register("Caption", typeof(string), typeof(Category), new PropertyMetadata(null));

    public ObservableCollection<Item> SubItems
    {
        get { return (ObservableCollection<Item>)GetValue(SubItemsProperty); }
        set { SetValue(SubItemsProperty, value); }
    }
    public static readonly DependencyProperty SubItemsProperty =
        DependencyProperty.Register("SubItems", typeof(ObservableCollection<Item>), typeof(Category), new PropertyMetadata(null));
}
public class Item : DependencyObject
{
    public string Header
    {
        get { return (string)GetValue(HeaderProperty); }
        set { SetValue(HeaderProperty, value); }
    }
    public static readonly DependencyProperty HeaderProperty =
        DependencyProperty.Register("Header", typeof(string), typeof(Item), new PropertyMetadata(null));
}
public class MenuViewModel : DependencyObject
{
    public ObservableCollection<Category> MenuCategories
    {
        get { return (ObservableCollection<Category>)GetValue(MenuCategoriesProperty); }
        set { SetValue(MenuCategoriesProperty, value); }
    }
    public static readonly DependencyProperty MenuCategoriesProperty =
        DependencyProperty.Register("MenuCategories", typeof(ObservableCollection<Category>), typeof(MenuViewModel), new PropertyMetadata(null));

    public MenuViewModel()
    {
        MenuCategories = new ObservableCollection<Category>()
        {
            new Category() {Caption = "_One", SubItems = new ObservableCollection<Item>() { new Item() { Header = "_one"}, new Item() { Header = "t_wo" }, new Item() { Header = "_three" } } },
            new Category() {Caption = "_Two", SubItems = new ObservableCollection<Item>() { new Item() { Header = "_one"}, new Item() { Header = "t_wo" }, new Item() { Header = "_three" } } },
        };
    }
}
public partial class Test1Window : Window
{
    public Test1Window()
    {
        InitializeComponent();
        DataContext = new MenuViewModel();
    }
}
public class MenuItemContainerTemplateSelector : ItemContainerTemplateSelector
{
    public override DataTemplate SelectTemplate(object item, ItemsControl parentItemsControl)
    {
        var key = new DataTemplateKey(item.GetType());
        return (DataTemplate)parentItemsControl.FindResource(key);
    }
}

xaml 1.尝试:

<Window x:Class="DynamicMenuTest.Test1Window"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:DynamicMenuTest"
    mc:Ignorable="d"
    Title="Test1Window" Height="300" Width="300">
<Window.Resources>

    <local:MenuItemContainerTemplateSelector x:Key="MenuItemContainerTemplateSelector"/>

    <DataTemplate DataType="{x:Type local:Item}">
        <MenuItem Header="{Binding Header}">
            <MenuItem.HeaderTemplate>
                <DataTemplate>
                    <AccessText VerticalAlignment="Center" Text="{Binding}" />
                </DataTemplate>
            </MenuItem.HeaderTemplate>
        </MenuItem>
    </DataTemplate>

    <HierarchicalDataTemplate DataType="{x:Type local:Category}" ItemsSource="{Binding SubItems}">
        <MenuItem VerticalContentAlignment="Center">
            <!-- Hotkey works but doesn't show up -->
            <MenuItem.Header>
                <AccessText Text="{Binding Caption}"/>
            </MenuItem.Header>
        </MenuItem>
    </HierarchicalDataTemplate>

</Window.Resources>
<Grid>
    <Menu ItemsSource="{Binding MenuCategories}"
        UsesItemContainerTemplate ="true"
        ItemContainerTemplateSelector="{StaticResource MenuItemContainerTemplateSelector}"
    />
</Grid>

Xaml 2.尝试:

<Window x:Class="DynamicMenuTest.Test2Window"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:DynamicMenuTest"
    mc:Ignorable="d"
    Title="Test2Window" Height="300" Width="300">
<Window.Resources>

    <local:MenuItemContainerTemplateSelector x:Key="MenuItemContainerTemplateSelector"/>

    <DataTemplate DataType="{x:Type local:Item}">
        <MenuItem Header="{Binding Header}">
            <MenuItem.HeaderTemplate>
                <DataTemplate>
                    <AccessText VerticalAlignment="Center" Text="{Binding}" />
                </DataTemplate>
            </MenuItem.HeaderTemplate>
        </MenuItem>
    </DataTemplate>

    <HierarchicalDataTemplate  DataType="{x:Type local:Category}" ItemsSource="{Binding SubItems}">
        <MenuItem 
            Header="{Binding Caption}"
            VerticalContentAlignment="Center">

            <!-- Hotkey shows up but menu not working -->
            <MenuItem.HeaderTemplate>
                <DataTemplate>
                    <ContentPresenter RecognizesAccessKey="True" Content="{Binding }" VerticalAlignment="Center" Margin="4,0"/>
                </DataTemplate>
            </MenuItem.HeaderTemplate>
        </MenuItem>
    </HierarchicalDataTemplate>

</Window.Resources>
<Grid>
    <Menu ItemsSource="{Binding MenuCategories}"
        UsesItemContainerTemplate ="true"
        ItemContainerTemplateSelector="{StaticResource MenuItemContainerTemplateSelector}"
    />
</Grid>

Xaml 3.尝试:

<Window x:Class="DynamicMenuTest.Test3Window"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:DynamicMenuTest"
    mc:Ignorable="d"
    Title="Test3Window" Height="300" Width="300">
<Window.Resources>

    <local:MenuItemContainerTemplateSelector x:Key="MenuItemContainerTemplateSelector"/>

    <DataTemplate DataType="{x:Type local:Item}">
        <MenuItem Header="{Binding Header}">
            <MenuItem.HeaderTemplate>
                <DataTemplate>
                    <AccessText VerticalAlignment="Center" Text="{Binding}" />
                </DataTemplate>
            </MenuItem.HeaderTemplate>
        </MenuItem>
    </DataTemplate>

    <HierarchicalDataTemplate  DataType="{x:Type local:Category}" ItemsSource="{Binding SubItems}">
        <MenuItem 
            Header="{Binding Caption}"
            VerticalContentAlignment="Center">
            <!-- Hotkey shows up but menu doesn't work -->
            <MenuItem.HeaderTemplate>
                <DataTemplate>
                    <AccessText Text="{Binding}" VerticalAlignment="Center" Margin="4,0"/>
                </DataTemplate>
            </MenuItem.HeaderTemplate>
        </MenuItem>
    </HierarchicalDataTemplate>

</Window.Resources>
<Grid>
    <Menu ItemsSource="{Binding MenuCategories}"
        UsesItemContainerTemplate ="true"
        ItemContainerTemplateSelector="{StaticResource MenuItemContainerTemplateSelector}"
    />
</Grid>

1 个答案:

答案 0 :(得分:1)

您的DataTemplateHierarchicalDataTemplate描述了MenuItem的标题内容应如何显示,因此嵌套另一个MenuItem是个坏主意。相反,保持简单和享受:

    <DataTemplate DataType="{x:Type local:Item}">
        <AccessText VerticalAlignment="Center" Text="{Binding Header}" />
    </DataTemplate>

    <HierarchicalDataTemplate DataType="{x:Type local:Category}" ItemsSource="{Binding SubItems}">
        <AccessText Text="{Binding Caption}"/>
    </HierarchicalDataTemplate>