.net WPF - 如何强制命令通过其 CommandBindings 重新评估“CanExecute”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1340302/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF - How to force a Command to re-evaluate 'CanExecute' via its CommandBindings
提问by Drew Noakes
I have a Menuwhere each MenuItemin the hierarchy has its Commandproperty set to a RoutedCommandI've defined. The associated CommandBindingprovides a callback for the evaluation of CanExecutewhich controls the enabled state of each MenuItem.
我有一个层次结构Menu中的每个属性都设置为我定义的属性。关联提供了一个用于评估的回调,该回调控制每个 的启用状态。MenuItemCommandRoutedCommandCommandBindingCanExecuteMenuItem
This almostworks. The menu items initially come up with the correct enabled and disabled states. However when the data that my CanExecutecallback uses changes, I need the command to re-request a result from my callback in order for this new state to be reflected in the UI.
这几乎有效。菜单项最初具有正确的启用和禁用状态。但是,当我的CanExecute回调使用的数据发生变化时,我需要命令从我的回调中重新请求结果,以便在 UI 中反映这个新状态。
There do not appear to be any public methods on RoutedCommandor CommandBindingfor this.
似乎没有任何关于此RoutedCommand或CommandBinding为此的公共方法。
Note that the callback is used again when I click or type into the control (I guess it's triggered on input because mouse-over doesn't cause the refresh).
请注意,当我单击或输入控件时再次使用回调(我猜它是在输入时触发的,因为鼠标悬停不会导致刷新)。
回答by Arcturus
回答by CodingWithSpike
For anyone who comes across this later; If you happen to be using MVVM and Prism, then Prism's DelegateCommandimplementation of ICommandprovides a .RaiseCanExecuteChanged()method to do this.
对于以后遇到此问题的任何人;如果您碰巧使用 MVVM 和 Prism,那么 Prism 的DelegateCommand实现ICommand提供了一种.RaiseCanExecuteChanged()方法来执行此操作。
回答by Bek Raupov
I couldnt use CommandManager.InvalidateRequerySuggested();because I was getting performance hit.
我无法使用,CommandManager.InvalidateRequerySuggested();因为我的性能受到了影响。
I have used MVVM Helper's Delegating command, which looks like below (i have tweaked it a bit for our req). you have to call command.RaiseCanExecuteChanged()from VM
我使用了MVVM Helper的 Delegating 命令,如下所示(我已经根据我们的要求对其进行了一些调整)。你必须command.RaiseCanExecuteChanged()从VM调用
public event EventHandler CanExecuteChanged
{
add
{
_internalCanExecuteChanged += value;
CommandManager.RequerySuggested += value;
}
remove
{
_internalCanExecuteChanged -= value;
CommandManager.RequerySuggested -= value;
}
}
/// <summary>
/// This method can be used to raise the CanExecuteChanged handler.
/// This will force WPF to re-query the status of this command directly.
/// </summary>
public void RaiseCanExecuteChanged()
{
if (canExecute != null)
OnCanExecuteChanged();
}
/// <summary>
/// This method is used to walk the delegate chain and well WPF that
/// our command execution status has changed.
/// </summary>
protected virtual void OnCanExecuteChanged()
{
EventHandler eCanExecuteChanged = _internalCanExecuteChanged;
if (eCanExecuteChanged != null)
eCanExecuteChanged(this, EventArgs.Empty);
}
回答by Andrue Cope
If you have rolled your own class that implements ICommandyou can lose a lot of the automatic status updates forcing you to rely on manual refreshing more than should be needed. It can also break InvalidateRequerySuggested(). The problem is that a simple ICommandimplementation fails to link the new command to the CommandManager.
如果您已经推出了自己的实现类,ICommand您可能会失去很多自动状态更新,从而迫使您更多地依赖手动刷新。它也可以打破InvalidateRequerySuggested()。问题是一个简单的ICommand实现无法将新命令链接到CommandManager.
The solution is to use the following:
解决方法是使用以下方法:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
This way subscribers attach to CommandManagerrather than your class and can properly participate in command status changes.
通过这种方式,订阅者可以附加到CommandManager您的班级而不是您的班级,并且可以正确参与命令状态更改。
回答by Fabio Angela
I've implemented a solution to handle property dependency on commands, here the link https://stackoverflow.com/a/30394333/1716620
我已经实现了一个解决方案来处理对命令的属性依赖,这里是链接https://stackoverflow.com/a/30394333/1716620
thanks to that you'll end up having a command like this:
多亏了这一点,你最终会得到这样的命令:
this.SaveCommand = new MyDelegateCommand<MyViewModel>(this,
//execute
() => {
Console.Write("EXECUTED");
},
//can execute
() => {
Console.Write("Checking Validity");
return PropertyX!=null && PropertyY!=null && PropertyY.Length < 5;
},
//properties to watch
(p) => new { p.PropertyX, p.PropertyY }
);
回答by rmustakos
This is what worked for me: Put the CanExecute before the Command in the XAML.
这对我有用:将 CanExecute 放在 XAML 中的命令之前。

