2009-04-21 3 views
133

примеры Большинство MVVM я проработали имел модель реализации INotifyPropertyChanged, но в Josh Smith's CommandSink exampleмодели представления реализует INotifyPropertyChanged.В MVVM должна быть реализована модель ViewModel или Model INotifyPropertyChanged?

Я все еще познавательно воедино концепции MVVM, так что я не знаю, если:

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

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

+1

если реализовать INPC, дайте https://github.com/Fody/PropertyChanged попробовать - это сэкономит вам недели типизации. –

ответ

81

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

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

+71

Что вы будете делать, если свойство изменится в модели? Вам нужно как-то добраться до модели представления. Честный вопрос, я имею дело с этой загадкой прямо сейчас. –

+4

EventAggregator в коде Prism является хорошей альтернативой INotifyPropertyChanged для модели с измененным типом события. Код события в этом проекте поддерживает пересылку событий между фоном и потоками пользовательского интерфейса, что иногда может быть проблемой. –

+0

@Roger - как небольшая уступка вашему использованию, вы можете создать событие, которое может использовать viewmodel, которое вызывается при обновлении пользовательского интерфейса. – Steve

2

Я бы сказал в вашей модели ViewModel. Это не является частью модели, поскольку модель является агностикой UI. Модель должна быть «все, что ИСКЛЮЧЕНИЕ бизнес агностик»

7

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

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

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

+3

Как именно вы распространяете OnPropertyControl на OnPropertyChanged на ViewModel? У меня проблема, когда ViewModel имеет разные имена свойств, чем Model - для этого потребуется какое-то сопоставление имен от имени, верно? –

+0

Это не что-то действительно сложное, мы просто пересылаем события.Я полагаю, что если имена были разными, можно было бы использовать таблицу поиска. Если изменение не было взаимно однозначным, то вы могли бы просто подключить событие, а затем запустить необходимые события в обработчике. –

24

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

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

+0

очень приятно, спасибо за ссылку –

+0

Это первое предложение подводит итоги других ответов довольно хорошо, imo. => UPVOTE! – j00hi

2

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

119

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

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

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

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

Нижняя строка, когда вы видите, что кто-то утверждает, что «вы не можете делать то или это», это знак того, что они не знают, о чем говорят.

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

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

+5

Подумайте об этом так. Если вы, как разработчик, потребляете .dll с помощью моделей, вы, разумеется, не переписываете их для поддержки INotifyPropertyChanged. –

+0

Полностью согласен с вами. Как и я, вам также может быть приятно узнать, что официальная документация MVVM (раздел модели) согласуется с нас. :-) – Noldorin

+0

«Тем не менее, tehre - это разные способы достижения вещей, но я всегда буду спорить в пользу простоты и избежать избыточности». Очень важно. –

8

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

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

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

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

+2

Отлично, если ваши данные изменяются только тогда, когда DataController меняет его. Если данные поступают из базы данных или какого-либо другого хранилища данных, которые могут предоставить другую возможность для изменения, вам может потребоваться указать информацию о VIEWMODEL (DataController в вашем шаблоне) и VIEW, когда это произошло. Вы можете либо опросить, используя DataController, либо нажать какой-либо внешний процесс на свой DataModel, и позволить DataModel отправлять уведомления об изменениях в ваш DataController. – ScottCher

+3

Вы совершенно правы. Дизайн-паттерны очень высокого уровня. В большинстве случаев шаблон дизайна заставляет вас делать все правильно, но время от времени они превращают вас в неправильный путь. Вы никогда не должны избегать делать что-то правильно, потому что это вне вашего шаблона дизайна. – Rhyous

0

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

see here

+1

эмм .. нет. Модель не может быть xml-файлом или базой данных. И модель не используется для предоставления данных. В противном случае его следует называть не «моделью», а «данными» ..? Модель используется для описания данных. Достаточно самообязательно, не так ли? :) – Taras

0

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

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

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

0

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

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

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

Notifier в бизнес-модели

  1. Как за домен ведомой, это правильно. Он должен решить, когда поднимать, а когда нет.

Недостатки

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

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

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

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

0

IMHO я думаю, что ViewModel реализует INotifyPropertyChange и модель может использовать уведомление на другой «уровень».

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

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

1

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

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

1

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

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

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

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

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

Давайте посмотрим на 2 различных реализаций одного и того же абстракции:

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 может измениться».

2

Ответ на этот вопрос ясен, если вы хотите придерживаться MV-VM.

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

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

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

+2

Цитата открыта для интерпретации. Я думаю, вы должны добавить свою интерпретацию, чтобы ваш ответ был ясен :-) –

0

Я согласен с ответом Паулы, внедрение 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.

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

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

https://stackoverflow.com/a/6923833/45382

Смежные вопросы