使用ICommand对象的CanExecuteCommand有什么性能影响。方法是一遍又一遍地执行的吗?
我需要迭代大约200个对象的集合,根据它确定是否应该启用绑定到Command的按钮? CanExecuteCommand是否会重复执行,这将使我的应用程序变慢
答案 0 :(得分:13)
ICommand
界面如下:
public interface ICommand
{
// two methods
bool CanExecute(object parameter);
void Execute(object parameter);
// one event
event EventHandler CanExecuteChanged;
}
每当您想要指示WPF应检查/调用CanExecuteChanged
方法时,都应引发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
,那么每当CanExecute
认为GUI上发生了一些有趣的事情时(即使它与您的收藏无关),您的CommandManager
就会被调用。如果您有50个命令,每次键入时,它都会重新检查所有50个命令。所以是的,这个可能是一个性能问题。但是,如果您的CanExecute
方法中的逻辑非常简单,则可能不是问题。要点:不要在CanExecute
方法中进行数据库或网络API调用。
捎带CommandManager.RequerySuggested
以提升ICommand.CanExecuteChanged
事件的替代方法是滚动您自己的RelayCommand
版本,您可以自行检查并手动引发CanExecuteChanged
或者查看Prism框架的DelegateCommand
类,它们不与CommandManager
绑定,你必须手动引发CanExecuteChanged
事件,你可以通过为{创建一个监听器来完成{1}}然后在命令上提升PropertyChanged
。
我同意上面的@Will。 CanExecuteChanged
可能会有80%以上的时间没有问题。如果您确实开始发现性能问题,那么您可以创建自己的RelayCommand版本或使用Prism RelayCommand
并手动提升DelegateCommand
。
答案 1 :(得分:0)
对于未来的googlers: 我创建了一个有点不同的命令实现。例如,它绑定到ViewModelBase类的OnPropertyChanged事件,但它也允许View Model为其中的所有Command实例引发CanExecuteChanged事件,无论属性如何变化,例如单向的情况来源绑定方案。 此解决方案是PerrypheralFrameowrk.WPF程序集的一部分,可在nuget和codeplex上使用。仔细看看。 codeplex wiki有详细的文档,程序集中的类也是如此。