Реализация Josh Smith RelayCommand испорчена?

Считайте ссылку 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; }
}
  1. Делает эту утечку слабая ссылка до RelayCommandклиент, требуя, что пользователь RelayCommand поймите реализацию CanExecuteChanged и поддержите живую ссылку самостоятельно?
  2. Если так, делает это имеет смысл к, например, изменяет реализацию 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; 
        }
    }
    

41
задан Gennady Vanin Геннадий Ванин 20 April 2013 в 10:29
поделиться

3 ответа

Что ж, согласно Reflector, он реализован таким же образом в классе RoutedCommand , так что я думаю, что все в порядке ... если только кто-то из команды WPF ошибся;)

7
ответ дан 27 November 2019 в 00:43
поделиться

Я могу упустить суть здесь, но разве следующее не является сильной ссылкой на обработчик событий в конструкторе?

    _canExecute = canExecute;           
0
ответ дан 27 November 2019 в 00:43
поделиться

Я считаю, что это ошибочно.

Перенаправляя события в CommandManager, вы получаете следующее поведение

Это гарантирует, что команда WPF инфраструктура просит все RelayCommand объекты, если они могут выполняться в любое время он запрашивает встроенные команды.

Однако что произойдет, если вы захотите сообщить всем элементам управления, привязанным к одной команде, для повторной оценки состояния CanExecute? В его реализации вы должны перейти в CommandManager, что означает

. Каждая отдельная привязка команды в вашем приложении переоценивается

Это включает в себя все те, которые не имеют значения, кучу бобов, те, в которых оценка CanExecute имеет побочные эффекты. (например, доступ к базе данных или длительные задачи), которые ждут своей очереди ... Это все равно, что забить гвоздь кувалдой.

Вы должны серьезно подумать о последствиях этого.

5
ответ дан 27 November 2019 в 00:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: