我的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)?有没有更好的方法来实现这个目标?
答案 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属性。视图模型将使用类似的
返回falsethis.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孩子呢