Я просмотрел несколько руководств MVVM, и я видел, как это делалось в обоих направлениях. Большинство используют ViewModel для PropertyChanged (это то, что я делал), но я натолкнулся на тот, который сделал это в модели. Оба метода приемлемы? Если да, то каковы преимущества/недостатки различных методов?
MVVM - PropertyChanged в модели или ViewModel?
Ответ 1
Интерфейс INotifyPropertyChanged
(INPC) используется для Binding
.
Итак, в среднем случае вы хотите реализовать его в своем ViewModel
.
ViewModel
используется для развязки Model
с вашего View
, поэтому нет необходимости иметь INPC в вашем Model
, так как вы не хотите, чтобы Bindings
был вашим Model
.
В большинстве случаев даже для более мелких свойств у вас все еще есть очень маленький ViewModel
.
Если вам нужна прочная база для MVVM
, вы, вероятно, собираетесь использовать какую-то MVVM Framework, например caliburn.micro. Используя его, вы получите ViewModelBase
(или здесь NotifyPropertyChangedBase
), так что вам не нужно будет самостоятельно выполнять эти элементы интерфейса, и вы можете просто использовать NotifyOfPropertyChange(() => MyProperty)
, что проще и менее подвержено ошибкам.
UPDATE Поскольку, похоже, есть много разработчиков Windows Forms, вот отличный статья, которая даст более глубокое понимание того, что такое MVVM: Журнал MSDN на MVVM
Я связал, в частности, ту часть о датемодели, о которой идет речь.
Ответ 2
Microsoft Patterns and Practices, изобретатель MVVM, и я все не согласен с выбранным ответом.
Как правило, модель реализует средства, которые упрощают привязку к представлению. Обычно это означает, что он поддерживает уведомление об изменении свойств и коллекции с помощью интерфейсов INotifyPropertyChanged и INotifyCollectionChanged. Классы моделей, представляющие коллекции объектов, обычно выводятся из класса ObservableCollection, который обеспечивает реализацию интерфейса INotifyCollectionChanged.
- Microsoft Patterns and Practices: http://msdn.microsoft.com/en-us/library/gg405484%28v=pandp.40%29.aspx#sec4
В этот момент вступает в действие привязка данных. В простых примерах представление представляет собой данные, привязанные непосредственно к модели. Части Модели просто отображаются в представлении путем односторонней привязки данных. Другие части модели могут быть отредактированы путем непосредственного связывания элементов управления в двух направлениях с данными. Например, логическое значение в модели может быть привязано к элементу CheckBox или строковому полю TextBox.
- Джон Госсман, изобретатель MVVM: http://blogs.msdn.com/b/johngossman/archive/2005/10/08/478683.aspx
Моя собственная статья: http://www.infoq.com/articles/View-Model-Definition
Это анти-шаблон, имеющий "модель представления", которая просто обертывает модель и предоставляет тот же список свойств. Задача модели представления - вызывать внешние службы и выставлять отдельные и коллекции моделей, возвращаемых этими службами.
Причины:
- Если модель обновляется напрямую, модель представления не будет знать, чтобы запустить событие с измененным свойством. Это приводит к тому, что пользовательский интерфейс выходит из строя.
- Это сильно ограничивает возможности отправки сообщений между родительскими и дочерними представлениями.
- Если модель изменила свое собственное свойство, # 1 и 2 не являются проблемой. Вместо этого вам приходится беспокоиться о утечке памяти, если VM-оболочка выходит из области видимости, но модель не работает.
- Если ваши модели сложны, с множеством объектов-потомков, вам нужно пройти все дерево и создать второй граф объектов, который будет тени первого. Это может быть довольно утомительным и подверженным ошибкам.
- Обернутые коллекции особенно трудны для работы. Каждый раз, когда что-то (UI или бэкэнд) вставляет или удаляет элемент из коллекции, теневую коллекцию необходимо обновить, чтобы она соответствовала. Этот код действительно трудно получить.
Это не значит, что вам никогда не понадобится модель представления, которая обертывает модель. Если ваша модель просмотра предоставляет свойства, существенно отличающиеся от модели, и их нельзя просто перепечатать с помощью IValueConverter, тогда модель просмотра с оболочкой имеет смысл.
Еще одна причина, по которой вам может понадобиться модель просмотра оболочки, заключается в том, что по каким-то причинам ваши классы данных не поддерживают привязку данных. Но даже тогда обычно лучше просто создать обычную, привязываемую модель и скопировать данные из исходных классов данных.
И, конечно, ваша модель представления будет иметь специфические свойства пользовательского интерфейса, например, какой элемент в коллекции выбран.
Ответ 3
Согласился бы с Джонатаном Алленом.
Если вам нечего добавить в "View-Model" ( "Команды", свойства, специфичные для представления, которые влияют на презентацию и т.д.), я бы определенно реализовал INotifyPropertyChanged в модели и разоблачил это напрямую (если можно - "модель" 'не может быть вашим. Мало того, что вы в конечном итоге повторяете много кода шаблона, поддерживая синхронизацию двух символов, является абсолютной болью.
INotifyPropertyChanged не является интерфейсом, зависящим от вида, он делает только то, что предлагает название, - вызывает событие при изменении свойства. WinForms, WPF и Silverlight просто поддерживают его для Binding - я определенно использовал его для непредставленных целей!
Ответ 4
Как правило, любой объект, с которым вы будете привязываться (даже если вам не нужна двусторонняя привязка и уведомление об изменении свойства), должен реализовать INotifyPropertyChanged
. Это происходит потому, что не удается сделать это Может вызвать утечку памяти
Ответ 5
INotifyPropertyChanged должен быть реализован всеми типами, потребляемыми представлением (если только он имеет только постоянные значения).
Вы возвращаете модели (не viewmodels) в представление? Если да, то он должен реализовать INotifyPropertyChanged.
Ответ 6
В то время как я вообще поддерживаю модель, внедряющую INPC, вызов INPC в составной модели представления - это когда он выдает предполагаемые свойства, которые могут быть привязаны к представлению. ИМО, поскольку INPC запекается в System.dll, модель, реализующая его, может считаться POCO. Для коллекций есть преимущество производительности на основе модели INPC. На 64-битной платформе виртуальная машина-обертка будет иметь 8-множитель коэффициентов по размеру байта (загрузить расширение отладчика SOS для фактического размера) ObservableCollection <ViewModel> по сравнению с ObservableCollection <Model> .
Ответ 7
Создатель MVVM ДжонГоссман заявляет в этой статье в блоге (упомянутой @Jonathan Allen), что:
В простых примерах представление представляет собой данные, привязанные непосредственно к Модели. Части модели просто отображаются в представлении односторонними данными связывание. Другие части модели могут быть отредактированы путем прямого связывания управляет двусторонним доступом к данным. Например, логическое значение в модели может быть связанными данными с CheckBox или строковым полем в TextBox.
Однако на практике только небольшое подмножество пользовательского интерфейса приложения может быть данными привязаны непосредственно к Модели, особенно если Модель является уже существующей класс или данные, по которым разработчик приложения не имеет контроль.
Я предпочитаю следовать практике, которая по-прежнему применима, когда приложение масштабируется.
Если "На практике [...] только небольшое подмножество пользовательского интерфейса приложения может быть привязано непосредственно к модели", это, похоже, не является хорошей практикой, поскольку я не планирую заниматься только "простой" случаи "или" небольшое подмножество пользовательского интерфейса приложения ".
Для "простых случаев" я бы даже не использовал MVVM для начала.