如何在有UI交互的情况下阻止CommandManager调用CanExecute?

时间:2015-01-12 22:36:06

标签: c# wpf xaml relaycommand

我们的UI目前有很多控件绑定到一些复杂CanExecutes的命令。我们面临的问题是,只要CommandManager确定需要重新评估UI,所有命令都会运行CanExecute,这反过来会对特定情况造成相当大的性能损失。

阅读这篇文章:How does CommandManager.RequerySuggested work?

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

1 个答案:

答案 0 :(得分:1)

解决方案可能是实现一个简单版本的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);
        }
    }
}

然后在viewModel中调用以下命令重新评估命令:

fooCommand.Invalidate();

当然,这会让您遇到相反的问题,即您现在必须手动重新评估所有命令......

修改

要详细说明评论,大多数RelayCommand都会像这样实施CanExecuteChanged事件:

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

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

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