Интерфейс ICommand
выглядит следующим образом:
public interface ICommand
{
// two methods
bool CanExecute(object parameter);
void Execute(object parameter);
// one event
event EventHandler CanExecuteChanged;
}
Событие CanExecuteChanged
следует вызывать в любое время, когда вы хотите указать, что метод CanExecute
должен быть проверен/вызван WPF. Тот, кто реализует ICommand
, должен вызвать событие, и тот, кому нужно обновить состояние включения кнопки в графическом интерфейсе (система WPF), должен зарегистрироваться и обработать событие, и оно вызывает CanExecute
.
В классе RelayCommand
Джоша Смита он использует встроенный класс CommandManager
WPF для повышения CanExecuteChanged
:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
По сути, CommandManager
в WPF — это синглтон, который прослушивает все виды маршрутизируемых событий: KeyUpEvent, MouseUpEvent и т. д., а затем сообщает всем «привет, произошло что-то интересное», вызывая свое событие RequerySuggested
. Поэтому, если вы используете RelayCommand
, ваш CanExecute
будет вызываться каждый раз, когда CommandManager
думает, что в графическом интерфейсе произошло что-то интересное (даже если это не имеет ничего общего с вашей коллекцией). Если у вас есть 50 команд, каждый раз, когда вы нажимаете клавишу, он перепроверяет все 50 команд. Так что да, это может быть проблемой производительности. Однако, если ваша логика в вашем методе CanExecute
действительно проста, это, вероятно, не проблема. Вывод: не делайте вызовы API базы данных или сети в методе CanExecute
.
Альтернативой использованию CommandManager.RequerySuggested
для создания события ICommand.CanExecuteChanged
является использование собственной версии RelayCommand
, в которой вы выполняете свою собственную проверку и создаете CanExecuteChanged
вручную, или смотрите на класс DelegateCommand
среды Prism, где они не связаны с CommandManager
, и вы необходимо вручную вызвать событие CanExecuteChanged
, что вы, вероятно, могли бы сделать, создав прослушиватель для PropertyChanged
, а затем подняв CanExecuteChanged
по команде.
Однако я согласен с @Will выше. RelayCommand
, вероятно, будет работать более 80% времени без проблем. Если вы начинаете обнаруживать проблемы с производительностью, вы можете создать свою собственную версию RelayCommand или использовать Prism DelegateCommand
и поднять CanExecuteChanged
вручную.
person
Kendrick
schedule
07.09.2011