WPF - 如何强制命令
我有一个Menu
其中层次结构中的每个MenuItem
都有Command
属性设置为RoutedCommand
我定义了通过其化CommandBindings重新评估“CanExecute”。相关联的CommandBinding
为评估CanExecute
提供了回调,该回调控制每个MenuItem
的启用状态。WPF - 如何强制命令
这个差不多的作品。菜单项最初出现正确的启用和禁用状态。但是,当我的回调使用更改的数据时,我需要该命令重新请求我的回调中的结果,以便将此新状态反映到UI中。
对此,在RoutedCommand
或CommandBinding
上似乎没有任何公开方法。
请注意,当我单击或键入到控件中时(我猜它是由输入触发的,因为鼠标悬停不会导致刷新),回调会再次使用。
不是在书的最漂亮的,但你可以使用CommandManager所有无效的CommandBinding:
CommandManager.InvalidateRequerySuggested();
查看MSDN
更多信息对于任何人碰到这个以后谁上台;如果您碰巧使用MVVM和Prism,则Prism的DelegateCommand
实现ICommand
提供了一个.RaiseCanExecuteChanged()
方法来执行此操作。
此模式也可以在其他MVVM库中找到,例如MVVM Light。 – 2011-06-30 08:58:35
与Prism不同,MVVM Light v5的源代码指示其''RaiseCanExecuteChanged()'只是调用'CommandManager.InvalidateRequerySuggested()'。 – Peter 2015-08-21 14:18:25
对WPF中MVVM Light的一个注意事项,你需要使用命名空间GalaSoft.MvvmLight.CommandWpf,因为GalaSoft.MvvmLight.Command会造成麻烦http://www.mvvmlight.net/installing/changes#v5_0_2 – fuchs777 2016-01-29 12:49:26
我无法使用CommandManager.InvalidateRequerySuggested();
,因为我正在获得性能。
我已经使用MVVM Helper的Delegating命令,它看起来像下面(我已经调整了一下我们的req)。你必须调用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);
}
这样做效果更好为了我。谢谢。 – 2015-02-24 18:46:08
只是一个FYI我注释掉了CommandManager.RequerySuggested + = value;出于某种原因,我得到了一个对我的CanExecute代码进行近乎恒定/循环的评估。否则解决方案按预期工作。谢谢! – robaudas 2015-12-28 21:04:03
我已经实现了一个解决方案来处理命令财产的依赖性,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 }
);
如果您已经推出自己的类实现ICommand
你可以失去很多逼着你去依靠手工清爽超过应所需的自动状态更新。它也可以打破InvalidateRequerySuggested()
。问题是一个简单的ICommand
实现无法将新命令链接到CommandManager
。
的解决方案是使用以下命令:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
这样用户连接到CommandManager
,而不是你的类可以适当参与指挥状态的变化。
直截了当,让人们可以控制其ICommand实现。 – 2017-05-22 19:56:38
感谢这工作得很好。用户界面略有延迟,但我并不担心这一点。另外,我立即投了你的答案,然后投票回去看它是否有效。现在它正在工作,我无法再重新申请投票。不知道为什么SO有这个规则。 – 2009-08-27 11:17:15
我编辑了你的答案,以便重新申请我的投票。我没有改变编辑中的任何内容。再次感谢。 – 2009-08-27 11:18:14
哈哈OK :)谢谢! – Arcturus 2009-08-27 11:49:02