在什么情况下ICommand CanExecute可能不会更新?

时间:2016-03-01 13:33:39

标签: wpf

我已经在几个大型项目中使用Josh Smith's implementation of RelayCommand多年了。但是今天我遇到了一个场景,其中我的一个命令上的CanExecute并不令人耳目一新。我不知道是什么造成了它 - 视图模型并没有做任何我已经做过几十次的事情。

VM的构造函数创建了几个命令。第一个是"开始"命令: -

StartCommand = new RelayCommand(o => StartAsync(), o => true);

StartAsync()方法如下所示: -

private async void StartAsync()
{
    IsRunning = true;
    await Task.Run(() => SomeLongRunningProcess(); }
    IsRunning = false;
}

还有一个" save"命令: -

SaveCommand = new RelayCommand(o => Save(), o => !IsRunning);

(' IsRunning'是一个沼泽标准属性,实现了INotifyPropertyChanged。除了用于" CanExecute"委托之外,它还绑定到IsEnabled属性视图中的一些控件启用/禁用它们。)

当我点击我的"开始"按钮(绑定到' StartCommand'),"保存"按钮被正确禁用。 b / g进程运行完成,然后将IsRunning设置为false,但这并不会触发" Save"按钮启用。只有在我查看视图的某个位置时才会启用它。

(顺便说一下,IsEnabled属性绑定到VM IsRunning属性的控件正确启用和禁用。

我发现了一些关于此事的SO文章,但没有真正解释为什么会发生这种情况。我的解决方法是将按钮的IsEnabled属性绑定到&#39; IsRunning&#39;但令人沮丧的是,这个特殊视图拒绝播放。关于可能导致这种情况的任何想法?常识说它是特定于这个视图/虚拟机的东西,但是我很难过(而且我不会在这里发布代码 - 那里的代码太多了。)< / p>

1 个答案:

答案 0 :(得分:5)

是的,因为您使用的RelayCommand版本取决于CommandManager.RequerySuggested事件而且不准确。

documentation states

  

当CommandManager检测到可能更改的条件时发生   命令执行的能力。

基本上它会猜测可以更改数据的所有可能事件。它永远不会知道您的ViewModel / Model何时更改。它没有收听房产变更通知。

如果您想立即做出反应而不等待CommandManager猜测,则需要在模型更新时自行手动触发ICommand.CanExecuteChanged

您看到事件未被触发,除非您点击窗口或其他内容但请注意it could fire several times too