6

使用 ICommand 对象的 CanExecuteCommand 对性能有何影响。该方法是否一遍又一遍地执行?

我需要遍历大约 200 个对象的集合,根据这些对象决定是否应该启用绑定到命令的按钮?CanExecuteCommand 是否会重复执行,这会使我的应用程序变慢

4

2 回答 2

14

ICommand界面如下:

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

    // one event
    event EventHandler CanExecuteChanged;
}

CanExecuteChanged任何时候都应该引发该事件,以表明该CanExecute方法应该由 WPF 检查/调用。谁实现ICommand应该引发事件,谁需要刷新 GUI(WPF 系统)上的按钮启用状态应该注册并处理该事件并调用CanExecute.

在 Josh Smith 的RelayCommand课堂上,他使用 WPF 的内置CommandManager类 raise CanExecuteChanged

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

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

捎带CommandManager.RequerySuggested引发 ICommand.CanExecuteChanged事件的替代方法是滚动你自己的版本,RelayCommand你自己检查并CanExecuteChanged手动引发,或者查看 Prism 框架的DelegateCommand类,它们不绑定CommandManager,你必须手动引发CanExecuteChanged事件,您可以通过为该命令创建一个侦听器PropertyChanged然后引发CanExecuteChanged该命令来做到这一点。

我同意上面的@Will。RelayCommand可能会在 80% 以上的时间内正常工作。如果您确实开始发现性能问题,那么您可以创建自己的 RelayCommand 版本或使用 PrismDelegateCommandCanExecuteChanged手动提升。

于 2011-09-07T15:28:56.077 回答
0

对于未来的谷歌人:我创建了一个稍微不同的命令实现。一方面,它绑定到 ViewModelBase 类的 OnPropertyChanged 事件,但它也允许 View Model 为其内的所有 Command 实例引发 CanExecuteChanged 事件,而不管属性是否发生变化,例如在 One Way 的情况下到源绑定场景。此解决方案是 PerrypheralFrameowrk.WPF 程序集的一部分,可在 nuget 和 codeplex 上使用。查一下。codeplex wiki 有详细的文档,程序集中的类也是如此。

于 2014-11-01T21:56:52.097 回答