3

如果我有一个命令列表,其中每个命令都有一个组号,我如何在上下文菜单中显示这些命令?

下面是我尝试过的代码,但我似乎无法显示子菜单项。

namespace groupTest
{
    public class GroupedCommand
    {
        public string Name { get; set; }
        public ICommand Command { get; set; }
        public int Group { get; set; }
    }

    public partial class Window1 : Window
    {
        public List<GroupedCommand> Commands
        {
            get;
            private set;
        }

        public Window1()
        {
            Commands = new List<GroupedCommand>();
            Commands.Add(new GroupedCommand() { Name = "A", Group = 0 });
            Commands.Add(new GroupedCommand() { Name = "B", Group = 0 });
            Commands.Add(new GroupedCommand() { Name = "C", Group = 1 });
            Commands.Add(new GroupedCommand() { Name = "D", Group = 1 });

            var defView = (CollectionView)CollectionViewSource.GetDefaultView(Commands);
            defView.GroupDescriptions.Add(new PropertyGroupDescription("Group"));

            DataContext = this;
            InitializeComponent();
        }
    }
}

<Window x:Class="groupTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">

    <Window.ContextMenu>
        <ContextMenu ItemsSource="{Binding Commands}">
            <ContextMenu.GroupStyle>
                <GroupStyle>
                    <GroupStyle.ContainerStyle>
                        <Style TargetType="{x:Type GroupItem}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type GroupItem}">
                                        <MenuItem Header="{Binding}">
                                            <ItemsPresenter />
                                        </MenuItem>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </GroupStyle.ContainerStyle>
                </GroupStyle>
            </ContextMenu.GroupStyle>
        </ContextMenu>
    </Window.ContextMenu>
</Window>
4

1 回答 1

0

我已经设法通过更改控制模板GroupItem和附加行为来实现这一点。

我已经更换了以下ControlTemplate

<ControlTemplate TargetType="{x:Type GroupItem}">
    <MenuItem Header="{Binding}">
        <ItemsPresenter />
    </MenuItem>
</ControlTemplate>

<ControlTemplate TargetType="{x:Type GroupItem}">
    <MenuItem Header="{Binding}" ItemsSource="{Binding Items}" Style="{StaticResource GroupMenuItemStyle}" />
</ControlTemplate>

并且,然后添加了一个附加行为以在鼠标进入/离开时显示/隐藏子菜单项MenuItem

public static class GroupMenuBehavior
    {
        public static readonly DependencyProperty DummyProperty =
            DependencyProperty.RegisterAttached("Dummy", typeof (bool), typeof (GroupMenuBehavior), new PropertyMetadata(default(bool), PropertyChangedCallback));

        private static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
        {
            var mi = dependencyObject as MenuItem;
            if (mi == null) return;
            if (mi.IsLoaded)
            {
                AddHandlers(mi);
            }
            else
            {
                mi.Loaded += MiOnLoaded;
            }
        }

        private static void MiOnLoaded(object sender, RoutedEventArgs routedEventArgs)
        {
            var mi = (MenuItem) sender;
            mi.Loaded -= MiOnLoaded;
            AddHandlers(mi);
        }

        static void AddHandlers(MenuItem mi)
        {
            mi.MouseEnter += MiOnMouseEnter;
            mi.MouseLeave += MiOnMouseLeave;
        }

        private static void MiOnMouseLeave(object sender, MouseEventArgs mouseEventArgs)
        {
            var mi = (MenuItem)sender;
            if (mi.IsSubmenuOpen)
                mi.IsSubmenuOpen = false;
        }

        private static void MiOnMouseEnter(object sender, MouseEventArgs mouseEventArgs)
        {
            var mi = (MenuItem) sender;
            if (mi.Items != null && mi.Items.Count != 0)
                mi.IsSubmenuOpen = true;
        }

        public static void SetDummy(MenuItem menuItem, bool value)
        {
            menuItem.SetValue(DummyProperty, value);
        }

        public static bool GetDummy(MenuItem menuItem)
        {
            return (bool) menuItem.GetValue(DummyProperty);
        }
    }

并且,MenuItem 附加上述行为的样式:

<Style TargetType="{x:Type MenuItem}" x:Key="GroupMenuItemStyle">
    <Setter Property="local:GroupMenuBehavior.Dummy" Value="True" />
</Style>

我知道,这是一个丑陋的黑客/修复。但是,无法通过其他方式使其工作。

于 2013-10-29T22:57:27.123 回答