如何在禁用所有子级时禁用顶级WPF MenuItem?

时间:2011-05-13 13:12:35

标签: wpf contextmenu menuitem

我的WPF应用程序中的上下文菜单中有以下MenuItem:

<MenuItem Header="Email">
      <MenuItem Command="Commands:CommandRepository.GenerateUserEmailCommand"
                CommandParameter="{Binding Path=SelectedItems}"
                Header="Email User">
      </MenuItem>
      <MenuItem Command="Commands:CommandRepository.GenerateManagerEmailCommand"
                    CommandParameter="{Binding Path=SelectedItems}"
                    Header="Email Manager">
      </MenuItem>
</MenuItem>

问题是,当两个电子邮件命令都返回CanExecute = false,因此两个命令都被禁用时,顶级MenuItem“电子邮件”仍保持启用状态。我知道我可以将顶部菜单项的IsEnabled绑定到其Children属性,然后使用转换器来决定何时应该禁用它,但似乎这应该自动发生。这不是使用CommandBindings的全部意义(即他们为您处理IsEnabled)?有没有更好的方法来实现这个目标?

3 个答案:

答案 0 :(得分:1)

为什么您的“电子邮件”MenuItem会被禁用?只因为孩子们在吗?

我认为你使用多重绑定和转换器的方法是做你想要的好方法。

答案 1 :(得分:1)

我可以想到两种方法:

1)如果你不介意后面的代码(我试图用WPF避免它),你可以为IsEnabledChanged创建一个事件处理程序,检查IsEnabled属性是否设置为false。如果是,那么你可以做类似

的事情
ParentMenuItem.IsEnabled = ParentMenuItem.Items.Count( c => c is MenuItem && (c as MenuItem).IsEnabled == true) > 0

2)为Parent MenuItem和Child MenuItem类型创建一个ViewModel,并将父MenuItem视图的is Enabled绑定到视图模型的IsEnabled属性。视图模型将使用类似的

返回false
this.Children.Count(c => c.IsEnabled == true) > 0

答案 2 :(得分:1)

定义RootMenu命令,然后将其添加到根菜单

Header="Email" Command="Commands:CommandRepository.RootMenu" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=.}"   

将命令绑定到以下RootMenuCanExecute

    public static void DropDownMenuCanExecute(object sender, CanExecuteRoutedEventArgs e) {
        e.CanExecute = false;
        ItemsControl parent = e.Parameter as ItemsControl;
        if (parent.Items.Count == 0) { return; }
        foreach (var i in parent.Items) {
            ICommandSource cs = i as ICommandSource; if (cs==null) { continue; }
            if (cs.Command == null) { continue; }
            if (cs.Command.CanExecute(cs.CommandParameter)) { e.CanExecute = true; return; }
        }
    }

它有点cpu昂贵,但它的工作原理。 怎么没有太多的MenuItem孩子呢