使用 ICommand 对象的 CanExecuteCommand 对性能有何影响。该方法是否一遍又一遍地执行?
我需要遍历大约 200 个对象的集合,根据这些对象决定是否应该启用绑定到命令的按钮?CanExecuteCommand 是否会重复执行,这会使我的应用程序变慢
使用 ICommand 对象的 CanExecuteCommand 对性能有何影响。该方法是否一遍又一遍地执行?
我需要遍历大约 200 个对象的集合,根据这些对象决定是否应该启用绑定到命令的按钮?CanExecuteCommand 是否会重复执行,这会使我的应用程序变慢
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
事件告诉每个人“嘿,发生了一些有趣的事情”。因此,如果您正在使用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 版本或使用 PrismDelegateCommand
并CanExecuteChanged
手动提升。
对于未来的谷歌人:我创建了一个稍微不同的命令实现。一方面,它绑定到 ViewModelBase 类的 OnPropertyChanged 事件,但它也允许 View Model 为其内的所有 Command 实例引发 CanExecuteChanged 事件,而不管属性是否发生变化,例如在 One Way 的情况下到源绑定场景。此解决方案是 PerrypheralFrameowrk.WPF 程序集的一部分,可在 nuget 和 codeplex 上使用。查一下。codeplex wiki 有详细的文档,程序集中的类也是如此。