CanExecuteCommand是否有任何性能影响?

gan*_*ran 6 wpf mvvm relaycommand icommand

使用ICommand对象的CanExecuteCommand有什么性能影响.方法是一遍又一遍地执行的吗?

我需要迭代大约200个对象的集合,根据它确定是否应该启用绑定到Command的按钮?CanExecuteCommand是否会重复执行,这将使我的应用程序变慢

Ken*_*ick 13

ICommand界面如下:

public interface ICommand
{
    // two methods
    bool CanExecute(object parameter);
    void Execute(object parameter);

    // one event
    event EventHandler CanExecuteChanged;
}
Run Code Online (Sandbox Code Playgroud)

CanExecuteChanged每当您想要指示CanExecuteWPF应该检查/调用该方法时,都应该引发该事件.无论谁实现ICommand都应该引发事件,并且需要刷新GUI上的按钮启用状态的人(WPF系统)应该注册并处理事件并调用它CanExecute.

在Josh Smith的RelayCommand课上,他使用WPF的内置CommandManager类来提高CanExecuteChanged:

public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}
Run Code Online (Sandbox Code Playgroud)

从本质上讲,WPF CommandManager是一个单一的,可以监听各种路由事件:KeyUpEvent,MouseUpEvent等......然后通过提升它的RequerySuggested事件告诉所有人"嘿发生了一些有趣的事情" .因此,如果您正在使用RelayCommand,CanExecute每次CommandManager在GUI上发生有趣的事情(即使它与您的收藏无关)时,您的意愿就会被调用.如果您有50个命令,每次键入时,它都会重新检查所有50个命令.所以,是的,这可能是一个性能问题.但是,如果您的CanExecute方法中的逻辑非常简单,那么它可能不是问题.要点:不要在CanExecute方法中进行数据库或网络API调用.

捎带CommandManager.RequerySuggested提升 ICommand.CanExecuteChanged事件的另一种方法是滚动你自己的版本,RelayCommand你自己进行检查和CanExecuteChanged手动提升,或者查看Prism框架的DelegateCommand类,它们没有绑定CommandManager,你必须手动提升CanExecuteChanged事件你可以通过创建一个监听器PropertyChanged然后提高CanExecuteChanged命令来完成.

我同意上面的@Will.RelayCommand可能会有超过80%的时间没有问题.如果您确实开始发现性能问题,那么您可以创建自己的RelayCommand版本或使用Prism DelegateCommandCanExecuteChanged手动引发.