Считайте ссылку Josh Smith' статья WPF Apps With The Model-View-ViewModel Design Pattern, конкретно реализация в качестве примера a RelayCommand
(На рисунке 3). (Никакая потребность прочитать всю статью для этого вопроса.)
В целом я думаю, что реализация превосходна, но у меня есть вопрос о делегации CanExecuteChanged
подписки к CommandManager
RequerySuggested
событие. Документация для RequerySuggested
состояния:
Так как это событие статично, оно будет только содержать на обработчик как слабая ссылка. Объекты, которые прислушиваются к этому событию, должны сохранить сильную ссылку к своему обработчику событий для предотвращения его собрал "мусор". Это может быть выполнено при наличии частного поля и присвоении обработчика как значение прежде или после присоединения к этому событию.
Все же демонстрационная реализация RelayCommand
не поддерживает никакой подобный к подписанному обработчику:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
RelayCommand
клиент, требуя, что пользователь RelayCommand
поймите реализацию CanExecuteChanged
и поддержите живую ссылку самостоятельно?Если так, делает это имеет смысл к, например, изменяет реализацию RelayCommand
быть чем-то как следующее для смягчения потенциального преждевременного GC CanExecuteChanged
подписчик:
// This event never actually fires. It's purely lifetime mgm't.
private event EventHandler canExecChangedRef;
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
this.canExecChangedRef += value;
}
remove
{
this.canExecChangedRef -= value;
CommandManager.RequerySuggested -= value;
}
}
Что ж, согласно Reflector, он реализован таким же образом в классе RoutedCommand
, так что я думаю, что все в порядке ... если только кто-то из команды WPF ошибся;)
Я могу упустить суть здесь, но разве следующее не является сильной ссылкой на обработчик событий в конструкторе?
_canExecute = canExecute;
Я считаю, что это ошибочно.
Перенаправляя события в CommandManager, вы получаете следующее поведение
Это гарантирует, что команда WPF инфраструктура просит все RelayCommand объекты, если они могут выполняться в любое время он запрашивает встроенные команды.
Однако что произойдет, если вы захотите сообщить всем элементам управления, привязанным к одной команде, для повторной оценки состояния CanExecute? В его реализации вы должны перейти в CommandManager, что означает
. Каждая отдельная привязка команды в вашем приложении переоценивается
Это включает в себя все те, которые не имеют значения, кучу бобов, те, в которых оценка CanExecute имеет побочные эффекты. (например, доступ к базе данных или длительные задачи), которые ждут своей очереди ... Это все равно, что забить гвоздь кувалдой.
Вы должны серьезно подумать о последствиях этого.