如何防止 CommandManager 在有 UI 交互时调用 CanExecute

本文关键字:调用 CanExecute 交互 UI 何防止 CommandManager 在有 | 更新日期: 2023-09-27 18:37:13

我们的UI目前有很多控件绑定到具有一些复杂CanExecutes的命令。我们面临的问题是,每当CommandManager确定需要重新评估UI时,所有命令都会运行其CanExecute,这反过来又会导致特定场景的性能下降。

阅读这篇文章:CommandManager.RequerySuggest如何工作?

似乎CommandManager将重新评估简单的按键按下、鼠标移动事件等。有没有办法防止这种情况发生,而是让命令管理器在手动调用时重新评估?

如何防止 CommandManager 在有 UI 交互时调用 CanExecute

解决方案可能是实现 RelayCommand 类的更简单版本,该版本仅存储事件处理程序本身,并公开一个公共方法来在适当时触发它们:

public class RelayCommand : ICommand
{
    public event EventHandler CanExecuteChanged;
    // Further ICommand implementation omitted...
    public void Invalidate()
    {
        var handler = this.CanExecuteChanged;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }
}

然后,在视图模型中调用以下命令以重新评估该命令:

fooCommand.Invalidate();

当然,这给您留下了相反的问题,您现在必须手动重新评估所有命令......

编辑

为了详细说明注释,大多数RelayCommand 都像这样实现CanExecuteChanged事件:

public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}

当 UI 订阅命令的 CanExecuteChanged 事件时,它实际上是间接订阅了 CommandManager.RequerySuggested 事件,这就是为什么每次CommandManager建议重新查询时都会调用 CanExecute 方法的原因。

我建议的更简单RelayCommand通过不订阅CommandManager.RequerySuggested事件来避免此问题。