我有一个Menu
,其中层次结构中的每个MenuItem
都将其Command
属性设置为我定义的RoutedCommand
。相关的CommandBinding
为评估CanExecute
提供了一个回调,MenuItem
控制每个CanExecute
的启用状态。
这几乎可行。菜单项最初会显示正确的启用和禁用状态。但是当我的RoutedCommand
回调使用的数据发生变化时,我需要命令从我的回调中重新请求结果,以便在UI中反映这种新状态。
在CommandBinding
或CommandManager.InvalidateRequerySuggested();
上似乎没有任何公开方法。
请注意,当我单击或键入控件时再次使用回调(我猜它是在输入时触发的,因为鼠标悬停不会导致刷新)。
对于后来遇到此事的人;如果你恰好使用MVVM和Prism,那么Prism的ICommand
实现.RaiseCanExecuteChanged()
提供了CommandManager.InvalidateRequerySuggested();
方法来做到这一点。
我无法使用qazxsw poi,因为我的性能受到了打击。
我使用过MVVM Helper的Delegating命令,看起来如下(我已经调整了一下我们的req)。你必须从VM调用command.RaiseCanExecuteChanged()
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);
}
如果您已经推出了自己的实现ICommand
的类,那么您可能会丢失大量自动状态更新,这会导致您依赖手动刷新而不是需要更多。它也可以打破InvalidateRequerySuggested()
。问题是简单的ICommand
实现无法将新命令链接到CommandManager
。
解决方案是使用以下内容:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
这样订阅者可以附加到CommandManager
而不是您的类,并且可以正确地参与命令状态更改。
我已经实现了一个处理命令属性依赖的解决方案,这里是链接https://stackoverflow.com/a/30394333/1716620
多亏了你最终会得到这样的命令:
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 }
);
这对我有用:在XAML中将CanExecute放在命令之前。