当所有子菜单都被禁用时,如何禁用顶级 WPF 菜单项?

4

我在我的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时,两个命令都被禁用,但顶级菜单项“电子邮件”仍然可用。我知道我可能可以将顶部菜单项的IsEnabled绑定到其Children属性,然后使用转换器来决定何时应禁用它,但似乎这应该是自动发生的。这不是使用CommandBindings的全部意义吗(即它们为您处理IsEnabled)?有更好的方法来实现这一点吗?
3个回答

2
我可以想到两种方法来实现这个:
1)如果您不介意使用代码后台(我尽量避免在WPF中使用它),您可以创建一个事件处理程序来检查IsEnabledChanged是否被设置为false。如果是,您可以执行以下操作:
ParentMenuItem.IsEnabled = ParentMenuItem.Items.Count( c => c is MenuItem && (c as MenuItem).IsEnabled == true) > 0

2)为父菜单项和子菜单项创建ViewModel,并将父菜单项视图的is Enabled绑定到ViewModel的IsEnabled属性。 ViewModel会使用类似的方式返回false。

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

1
为什么你的“电子邮件”菜单项会因为子项而变为禁用状态呢?
我认为你使用多绑定和转换器的方法是实现你想要的功能的好方法。

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子元素。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接