Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf 在哪些情况下,ICommand可以执行而不更新?_Wpf - Fatal编程技术网

Wpf 在哪些情况下,ICommand可以执行而不更新?

Wpf 在哪些情况下,ICommand可以执行而不更新?,wpf,Wpf,几年来,我一直在几个大型项目中使用。但是今天我遇到了一个场景,其中一个命令上的CanExecute无法刷新。我不知道是什么导致了它-视图模型没有做任何我已经做了几十次的事情 VM的构造函数创建了几个命令。第一个是“启动”命令:- StartCommand = new RelayCommand(o => StartAsync(), o => true); SaveCommand = new RelayCommand(o => Save(), o => !IsRunning

几年来,我一直在几个大型项目中使用。但是今天我遇到了一个场景,其中一个命令上的CanExecute无法刷新。我不知道是什么导致了它-视图模型没有做任何我已经做了几十次的事情

VM的构造函数创建了几个命令。第一个是“启动”命令:-

StartCommand = new RelayCommand(o => StartAsync(), o => true);
SaveCommand = new RelayCommand(o => Save(), o => !IsRunning);
StartAsync()方法如下所示:-

private async void StartAsync()
{
    IsRunning = true;
    await Task.Run(() => SomeLongRunningProcess(); }
    IsRunning = false;
}
还有一个“保存”命令:-

StartCommand = new RelayCommand(o => StartAsync(), o => true);
SaveCommand = new RelayCommand(o => Save(), o => !IsRunning);
('IsRunning'是bog标准属性,实现INotifyPropertyChanged。它不仅用于“CanExecute”委托,还绑定到视图中一些控件的IsEnabled属性以启用/禁用它们)

当我单击“开始”按钮(绑定到“开始命令”)时,“保存”按钮被正确禁用。b/g流程运行到完成,然后IsRunning设置为false,但这不会触发“保存”按钮变为启用状态。它仅在我单击视图上的某个位置时启用

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


我看到过一些关于这方面的文章,但没有什么能真正解释为什么会发生这种情况。我的解决方法是将按钮的
IsEnabled
属性绑定到“IsRunning”,但令人沮丧的是,这个特定的视图拒绝玩球。你有没有想过是什么原因造成的?常识说这是这个视图/VM特有的东西,但我很困惑(我不打算在这里发布代码,因为代码太多了)。

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

是那个

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

基本上,它猜测所有可能发生的事件,在这些事件中,您的数据可能会被更改。它永远无法知道ViewModel/模型何时更改。它没有侦听属性更改通知

如果您想在不等待
CommandManager
猜测的情况下立即做出反应,则需要在模型更新时自己手动启动
ICommand.CanExecuteChanged


您看到,除非单击窗口或其他内容,否则不会触发事件,但请注意,

SomeLongRunningProcess()
后台线程还是UI线程以外的线程?这可能是对UI组件的跨线程访问问题吗?您的命令可能会实现
CanExecuteChanged
事件。你试过了吗?@CodingGorilla它是一个b/g线程,但是当它完成等待时,“IsRunning=false”在UI线程上发生。我在其他视图/虚拟机上的命令中使用了相同的技术,没有问题。@XAMlMAX我在这里看到了类似的东西:。然而,当我将此方法添加到我的RelayCommand实现中时,我得到了一个错误:“CanExecuteChanged事件只能出现在+=或-=”的左侧。请看一看。奇怪的是,为什么在我的其他视图/虚拟机上可以这样做,但不幸的是,我看不到我正在做的任何不同之处,所以我猜这是一些非常微妙的差异。我在某个地方读到只有鼠标和键盘事件触发CommandManager,但我对此有点怀疑。在我的虚拟机中有很多很多地方,我可以设置在命令的CanExecute逻辑中使用的属性(甚至只是私有变量)的值,当我离鼠标或键盘很远时,它通常“只起作用”。@AndrewStephens很难猜到。但我想键盘或鼠标事件并不是导致无效的唯一原因。若我并没有错的话,当窗口被激活/停用时,它们就会升起。若你们好奇的话,你们可以这样做