Можно ли, чтобы установщики свойств имели побочные эффекты с шаблоном MVVM?

Я пишу приложение WPF, которое предназначено для решения стандартных задач. Я действительно новичок в шаблонах WPF и MVVM, поэтому у меня в голове немного путаницы после прочтения множества различных подходов к MVVM в Интернете. Я хотел бы знать, как моя простая операция по обновлению источника данных DataGrid "идиоматична" для MVVM.

Допустим, у меня есть один набор данных и один выпадающий список. Комбо содержит список всех тренеров. Сетка данных показывает всех спортсменов, подготовленных выбранным тренером, поэтому комбинация действует как фильтр для данных в сетке данных:

<ComboBox ItemsSource="{Binding ListCoach}" DisplayMemberPath="last_name" SelectedValue=
"{Binding SelectedCoach}" SelectedValuePath="Id"/>

<DataGrid ItemsSource="{Binding Path=ListSportsman}" .....  </DataGrid>

Мой класс ViewModel изменяет содержимое DataGrid в установщике свойства SelectedCoach (это свойство является целью для значения Combobox):

  private int _selectedCoach;
  public int SelectedCoach
  {
     get { return _selectedCoach; }
     set
     {
        _selectedCoach = value;
        ListSportsman = new ObservableCollection<sportsmanset>(_serviceAgent.ListSportsmanOfCoach(value));
        NotifyPropertyChanged(vm => vm.SelectedCoach);
     }
  }

Разве такой код не пахнет? Или было бы более целесообразно подписаться на изменение свойства SelectedCoach и установить ListSportsman в отдельную функцию? (кстати, как подписаться на событие NotifyPropertyChanged вручную?)

3 ответа

Решение

Нет, этот код не "пахнет"!

Модель представления очень тесно связана с представлением, которое она "поддерживает". В представлении, которое вы описываете, эти два свойства очень тесно связаны, поэтому имело бы смысл, чтобы они были тесно связаны в вашей модели представления.

Кроме того, просто спросите себя, какую пользу принесет логика, заполняющая сетку данных, слабо связанная с обработкой событий? Это может позволить вам легче выполнять эту логику в результате какого-либо другого события или, возможно, разделить на два класса для повторного использования в другом месте вашего кода. Возможен ли какой-либо из этих сценариев? Если нет, то усложнение вашего кода без какой-либо причины является запахом самого кода!

Кстати, если вы хотите обрабатывать это вручную, вам нужно добавить обработчик событий в классы PropertyChanged событие.

Это не неправильно по определению, но есть одна вещь, которую следует учитывать:

В целом разработчики ожидают, что установщики и получатели будут быстрыми. Поэтому, если вы добавляете логику, которая занимает значительное время, вы можете захотеть выполнить эту логику асинхронно или заменить свойство методом Set, чтобы было ясно, что здесь задействована обработка.

Частью обработки может быть установка свойства, к которому может быть привязано представление.

Мой ответ: "Нет, все не в порядке". Хорошо для простого приложения / прототипа это хорошо, однако для более сложных сценариев или для разработки хороших привычек / показательных примеров - это не так.

Что делать вместо этого? Там нет "один размер подходит для всех ответов", но я бы порекомендовал, исходя из моего опыта:

  1. всегда держать установщик тупым, т.е. только установленное значение и NotifyPropertyChanged.
  2. попробуйте инкапсулировать дорогую бизнес-логику и другие побочные эффекты там, где это должно быть - в командах. Если это невозможно и должно запускаться сеттером, создайте наблюдаемый поток Rx из PropertyChanged и подпишитесь на него. Это может показаться излишним, но преимущества Rx для MVVM огромны. Вот возможный (но не самый лучший) способ сделать это: http://blog.leifbattermann.de/2015/06/21/viewmodel-property-to-observable-stream/
  3. (оффтоп, но не совсем) также не вызывают изменения простых зависимых свойств только для чтения внутри сеттера, вместо этого используйте https://github.com/StephenCleary/CalculatedProperties или аналогичные (я сомневаюсь, что в данный момент что-то лучше)
Другие вопросы по тегам