【问题标题】:Are there any performance implications with CanExecuteCommand?CanExecuteCommand 对性能有影响吗?
【发布时间】:2011-11-12 05:38:35
【问题描述】:

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

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

【问题讨论】:

  • 可以,但前提是您没有过早优化。
  • 你的评论会不会有点模棱两可。
  • 会,我也不太明白。我的验证是大约 200 个对象的迭代 - 树视图。它只是检查一个简单的属性,并且在运行一次时不会很耗时。我担心的是如果 CanExecute 被反复触发会使代码变慢。有人可以请点灯
  • Will 是这样说的:您在 CanExecute 中的代码不应该做太多事情,因为它确实可以经常被调用。但是你不应该只担心这个,如果这真的让你的程序变慢,即如果你可以测量由于对 CanExecute 的调用过多而导致的性能下降。

标签: wpf mvvm icommand relaycommand


【解决方案1】:

ICommand接口如下:

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

    // one event
    event EventHandler CanExecuteChanged;
}

CanExecuteChanged 事件应在您想要指示 WPF 应检查/调用 CanExecute 方法的任何时候引发。实现ICommand 的人应该引发该事件,而需要刷新GUI(WPF 系统)上的按钮启用状态的人应该注册并处理该事件并调用CanExecute

在 Josh Smith 的 RelayCommand 类中,他使用 WPF 内置的 CommandManager 类来提升 CanExecuteChanged

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

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

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

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

【讨论】:

  • 相关答案在这里:stackoverflow.com/questions/6634777/…
  • 感谢 Kendrick 和 Will,您的回答为我总结了这一点。我将把它放在 CanExecute 中并寻找任何性能滞后。如果我找到一个,那么将看看其他实现
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2014-01-05
    • 1970-01-01
    • 2019-11-04
    • 2012-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-01
    • 1970-01-01
    相关资源
    最近更新 更多