В MVVM должен ViewModel или Model реализовать INotifyPropertyChanged?

В большинстве примеров MVVM, с которыми я работал, была реализована модель INotifyPropertyChanged, но в пример Josh Smith CommandSink ViewModel реализует INotifyPropertyChanged.

Я все еще когнитивно собираю концепции MVVM, поэтому не знаю, если:

  • вам нужно поместить INotifyPropertyChanged в ViewModel, чтобы заставить CommandSink работать
  • Это просто аберрация нормы, и это не имеет значения.
  • у вас всегда должна быть реализация модели INotifyPropertyChanged, и это просто ошибка, которая была бы исправлена, если бы это было разработано из примера кода в приложение

Что было другим опытом в проектах MVVM, над которыми вы работали?

Ответ 1

Я бы сказал совсем наоборот: я всегда ставил мой INotifyPropertyChanged на моем ViewModel - вы действительно не хотите, чтобы загрязнять вашу модель с помощью определенной функции WPF, такой как INotifyPropertyChanged, этот материал должен сидеть в ViewModel.

Я уверен, что другие не согласятся, но так, как я работаю.

Ответ 2

Я категорически не согласен с концепцией, согласно которой Модель не должна реализовывать INotifyPropertyChanged. Этот интерфейс не зависит от пользовательского интерфейса! Это просто сообщает об изменении. Действительно, WPF интенсивно использует это для выявления изменений, но это не значит, что это интерфейс пользовательского интерфейса. Я бы сравнил это со следующим комментарием: "Шина - это автомобильный аксессуар". Конечно, но велосипеды, автобусы и т.д. Тоже им пользуются. Таким образом, не воспринимайте этот интерфейс как интерфейс.

Сказав это, это не обязательно означает, что я считаю, что Модель должна предоставлять уведомления. Фактически, как правило, модель не должна реализовывать этот интерфейс, если в этом нет необходимости. В большинстве случаев, когда данные сервера не передаются клиентскому приложению, модель может устареть. Но если слушать данные финансового рынка, то я не понимаю, почему модель не может реализовать интерфейс. Например, что если у меня есть логика, не связанная с пользовательским интерфейсом, например, служба, которая, когда она получает цену Bid или Ask для данного значения, выдает предупреждение (например, по электронной почте) или размещает заказ? Это может быть возможным чистым решением.

Тем не менее, существуют разные способы достижения цели, но я бы всегда выступал за простоту и избегал избыточности.

Что лучше? Определить события в коллекции или изменениях свойств в модели представления и распространить их на модель или иметь представление, чтобы обновить модель (через модель представления)?

Суть в том, что когда вы видите, что кто-то заявляет, что "вы не можете делать то или это", это признак того, что он не знает, о чем говорит.

Это действительно зависит от вашего случая, и на самом деле MVVM - это фреймворк с множеством проблем, и мне еще предстоит увидеть общую реализацию MVVM по всем направлениям.

Хотелось бы, чтобы у меня было больше времени, чтобы объяснить множество разновидностей MVVM и некоторые решения общих проблем - в основном, предоставленные другими разработчиками, но, думаю, мне придется сделать это в другой раз.

Ответ 3

В M-V-VM ViewModel всегда (модель не всегда) реализует INotifyPropertyChanged

Ознакомьтесь с шаблоном/инструментарием проекта M-V-VM из http://blogs.msdn.com/llobo/archive/2009/05/01/download-m-v-vm-project-template-toolkit.aspx. Он использует команду DelegateCommand для управления и должен быть отличным стартовым шаблоном для ваших проектов M-V-VM.

Ответ 4

Я думаю, что MVVM очень плохо назван и вызов ViewModel ViewModel заставляет многих пропустить важную функцию хорошо продуманной архитектуры, которая является DataController, которая управляет данными независимо от того, кто пытается ее трогать.

Если вы рассматриваете модель View как больше DataController и реализуете архитектуру, в которой ваш DataController является единственным элементом, который касается данных, вы никогда не будете касаться данных напрямую, но всегда используйте DataController. DataController полезен для пользовательского интерфейса, но необязательно только для пользовательского интерфейса. Это для бизнес-уровня, слоя пользовательского интерфейса и т.д.

DataModel -------- DataController ------ View
                  /
Business --------/

В итоге вы получите такую ​​модель. Даже бизнес должен касаться только данных с помощью ViewModel. Тогда ваша головоломка просто уходит.

Ответ 5

Это зависит от того, как вы реализовали свою модель. Моя компания использует бизнес-объекты, подобные объектам Lhotka CSLA, и широко использует INotifyPropertyChanged по всей бизнес-модели.

Наш механизм проверки достоверности основывается на том, чтобы быть уведомленным о том, что свойства изменяются через этот механизм, и он работает очень хорошо. Очевидно, что если вы используете другую реализацию, отличную от бизнес-объектов, где уведомление об изменениях не так критично для операции, вы можете иметь другие методы для обнаружения изменений в своей бизнес-модели.

У нас также есть модели для просмотра, которые распространяют изменения из Модели, если это необходимо, но сами модели просмотра прислушиваются к изменениям Модели.

Ответ 6

Но иногда (как в этой презентации текст ссылки) модель - это сервис, который поставляет приложения с некоторыми данными в Интернете, а затем вам необходимо дополнить уведомление о приходе новых данных или изменении данных с помощью событий...

Ответ 7

Я думаю, что ответ вполне ясен, если вы хотите придерживаться MV-VM.

см.: http://msdn.microsoft.com/en-us/library/gg405484(v=PandP.40).aspx

В шаблоне MVVM представление инкапсулирует UI и любую логику UI, модель представления инкапсулирует логику и состояние представления, а модель - бизнес-логику и данные.

"Представление взаимодействует с моделью представления посредством привязки данных, команд и событий уведомлений об изменениях. Модель представления запрашивает, наблюдает и координирует обновления модели, преобразовывая, проверяя и агрегируя данные, необходимые для отображения в представлении".

Ответ 8

Я согласен с ответом Пауло, что реализация INotifyPropertyChanged в моделях полностью приемлема и даже предлагается Microsoft -

Как правило, модель реализует средства, облегчающие привязку к представлению. Как правило, это означает, что он поддерживает свойство и сбор изменено уведомление через INotifyPropertyChanged и INotifyCollectionChanged интерфейсов. Классы моделей, представляющие коллекции объектов, обычно наследуются от класса ObservableCollection<T>, который обеспечивает реализацию интерфейса INotifyCollectionChanged.

Хотя вам решать, хотите ли вы этот тип реализации или нет, но помните -

Что если в ваших модельных классах не реализованы необходимые интерфейсы?

Иногда вам нужно будет работать с модельными объектами, которые не реализуют INotifyPropertyChanged, INotifyCollectionChanged, IDataErrorInfo или INotifyDataErrorInfo интерфейсов. В этих случаях модели представления может потребоваться обернуть объекты модели и предоставить необходимые свойства представлению. Значения для этих свойств будут предоставлены непосредственно объектами модели. Модель представления будет реализовывать необходимые интерфейсы для свойств, которые она предоставляет, чтобы представление могло легко привязать к ним данные.

Взято с - http://msdn.microsoft.com/en-us/library/gg405484(PandP.40).aspx

Я работал в некоторых проектах, где мы не реализовали INotifyPropertyChanged в наших моделях, и из-за этого мы столкнулись с множеством проблем; В VM требовалось ненужное дублирование свойств, и в то же время нам приходилось обновлять базовый объект (с обновленными значениями) перед передачей их в BL/DL.

Вы столкнетесь с проблемами, особенно если вам нужно работать с коллекцией объектов вашей модели (скажем, в редактируемой сетке или списке) или со сложными моделями; объекты модели не будут обновляться автоматически, и вам придется управлять всем этим в вашей виртуальной машине.

Ответ 9

Я бы сказал в вашем ViewModel. Он не является частью Модели, поскольку модель является агностиком. Модель должна быть "все, что ИСКЛЮЧАЕТ бизнес-агностик"

Ответ 10

Просто используйте INotifyPropertyChange в своей модели просмотра, а не в Модели,

модель обычно использует IDataErrorInfo для обработки ошибок проверки, поэтому просто держите в своей модели ViewModel, и вы правы на дороге MVVM.

Ответ 11

Я думаю, что все зависит от варианта использования.

Когда у вас есть простая модель с множеством свойств, вы можете реализовать ее с помощью INPC. Простым я имею в виду, что эта модель выглядит как POCO.

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

Поставьте себя в положение какой-то модельной сущности, которая должна взаимодействовать с некоторыми другими моделями. У вас есть различные мероприятия для подписки. Все они реализованы как INPC. Представьте, что у вас есть обработчики событий. Один огромный каскад if-clauses и/или переключателей clausses.

Еще одна проблема с INPC. Вы должны проектировать свои приложения, чтобы полагаться на абстракцию, а не на реализацию. Обычно это делается с использованием интерфейсов.

Посмотрим на две различные реализации одной и той же абстракции:

public class ConnectionStateChangedEventArgs : EventArgs
{
    public bool IsConnected {get;set;}
}

interface IConnectionManagerINPC : INotifyPropertyChanged
{
    string Name {get;}
    int ConnectionsLimit {get;}
    /*

    A few more properties

    */
    bool IsConnected {get;}
}

interface IConnectionManager
{
    string Name {get;}
    int ConnectionsLimit {get;}
    /*

    A few more properties

    */
    event EventHandler<ConnectionStateChangedEventArgs> ConnectionStateChanged;
    bool IsConnected {get;}
}

Теперь посмотрим на оба из них. Что говорит IConnectionManagerINPC? То, что некоторые из его свойств могут измениться. Вы не знаете, кто из них. Фактически, дизайн состоит в том, что изменяется только IsConnected, поскольку остальные из них доступны только для чтения.

Напротив, намерения IConnectionManager ясны: "Я могу сказать вам, что значение свойства IsConnected может измениться".

Ответ 12

Обычно ViewModel реализует INotifyPropertyChanged. Модель может быть любым (файл xml, база данных или даже объект). Модель используется для передачи данных в viewmodel, которая распространяется на представление.

см. здесь

Ответ 13

Предположим, что ссылка объекта в вашем представлении изменяется. Как вы будете уведомлять все свойства, которые необходимо обновить, чтобы показать правильные значения? Вызов OnPropertyChanged в вашем представлении для всех свойств объекта - это мусор с моей точки зрения.

Так что я должен позволить самому объекту уведомить кого-либо, когда значение в свойстве изменяется, и, на мой взгляд, я использую привязки типа Object.Property1, Object.Property2 и on. Таким образом, если я просто хочу изменить объект, который в настоящее время поддерживается в моем представлении, я просто делаю OnPropertyChanged("Object").

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

Ответ 14

Я использую интерфейс INotifyPropertyChange в модели. Фактически, изменение свойства модели должно запускаться только пользовательским интерфейсом или внешним клиентом.

Я заметил несколько преимуществ и недостатков:

Преимущества

Notifier находится в бизнес-модели

  • В соответствии с доменом, это правильно. Он должен решить, когда поднимать, а когда нет.

Недостатки

Модель имеет свойства (qty, rate, Commission, totalfrieght). Totalfrieght рассчитывается с использованием количества, ставки, изменения комиссии.

  • При загрузке значений из db общий расчет флага называется 3 раза (количество, ставка, комиссия). Он должен быть один раз.

  • Если скорость, qty назначается на бизнес-уровне, вызывается еще один уведомитель.

  • Должна быть опция отключения этого, возможно, в базовом классе. Однако разработчики могли забыть это сделать.

Ответ 15

imho Я думаю, что viewmodel реализует INotifyPropertyChange, и модель может использовать уведомление на другом уровне.

например, с некоторой службой документа и объектом документа у вас есть событие documentChanged, которое viewmodel слушает, чтобы очистить и перестроить представление. В редакторе viewmodel у вас есть свойство change для свойств документа для поддержки представлений. Если служба многое делает с сохраненным документом (обновлением даты изменения, последним пользователем и т.д.), Вы легко получаете перегрузку событий Ipropertychanged, и достаточно просто изменить документ.

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

Ответ 16

Все свойства, которые связаны с моим представлением, находятся в моих ViewModel (s). Таким образом, они должны реализовать интерфейс INotifyPropertyChanged. Поэтому View получает все изменения.

[Используя инструментарий MVVM Light, я позволил им наследовать от ViewModelBase.]

Модель содержит бизнес-логику, но не имеет ничего общего с представлением. Таким образом, нет необходимости в интерфейсе INotifyPropertyChanged.

Ответ 17

Реализация INPC в моделях может быть использована, если модели открыто представлены во ViewModel. Но, как правило, ViewModel обертывание моделей - это его собственные классы, чтобы уменьшить сложность модели (которая не должна быть полезной для привязки). В этом случае INPC должен быть реализован во ViewModel.