INotifyPropertyChanged против DependencyProperty во ViewModel - PullRequest
346 голосов
/ 15 ноября 2008

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

Мой вопрос: когда мне отдавать предпочтение одному? Есть ли различия в производительности? Это действительно хорошая идея, чтобы дать зависимости ViewModel для WPF? Что еще нужно учитывать при принятии проектного решения?

Ответы [ 14 ]

207 голосов
/ 23 апреля 2009

Кент написал интересный блог на эту тему: Просмотр моделей: POCOs против DependencyObjects .

Краткое резюме:

  1. DependencyObjects не помечены как сериализуемый
  2. Класс DependencyObject переопределяет и запечатывает Equals () и Методы GetHashCode ()
  3. DependencyObject имеет привязку к потоку - к нему можно получить доступ только на нити, на которой это было создано

Я предпочитаю подход POCO. Базовый класс для PresentationModel (он же ViewModel), который реализует интерфейс INotifyPropertyChanged, можно найти здесь: http://compositeextensions.codeplex.com

37 голосов
/ 03 ноября 2010

Согласно руководству по производительности WPF, DependencyObjects определенно работают лучше, чем POCO, которые реализуют INotifyPropertyChanged:

http://msdn.microsoft.com/en-us/library/bb613546.aspx

27 голосов
/ 15 ноября 2008

Выбор полностью зависит от вашей бизнес-логики и уровня абстракции пользовательского интерфейса. Если вы не хотите хорошего разделения, DP будет работать для вас.

DependencyProperties будет применяться в основном на уровне VisualElements, поэтому не будет хорошей идеей, если мы создадим много DP для каждого нашего бизнес-требования. Также для DP существует более высокая стоимость, чем для INotifyPropertyChanged. Когда вы разрабатываете WPF / Silverlight, постарайтесь спроектировать UI и ViewModel полностью раздельно, чтобы в любой момент мы могли изменить элементы управления Layout и UI (на основе темы и стилей)

См. Также этот пост - https://stackoverflow.com/questions/275098/what-applications-could-i-study-to-understand-datamodel-view-viewmodel. Ссылка содержит много ссылок на шаблон Model-View-ViewModel, который очень важен для этого обсуждения.

19 голосов
/ 16 ноября 2008

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

Свойства зависимостей подразумевают «когда это, делайте это», используя понятные статические метаданные. Это декларативный подход, который получает мой голос за элегантность.

16 голосов
/ 09 ноября 2011

Свойства зависимостей предназначены для поддержки привязки (в качестве цели) к элементам пользовательского интерфейса, а не к привязке источника к данным. Именно здесь INotifyProperty входит. С чистой точки зрения, вы не должны использовать DP в ViewModels.

"Чтобы быть источником привязки, свойство не обязательно должно быть свойством зависимости; вы можете использовать любое свойство CLR в качестве источника привязки. Однако, чтобы стать целью привязки, свойство должно быть свойством зависимости. Чтобы односторонняя или двусторонняя привязка была эффективной, исходное свойство должно поддерживать уведомления об изменениях, которые распространяются на систему привязки и, следовательно, на цель. Для пользовательских источников привязки CLR это означает, что свойство должно поддержка INotifyPropertyChanged. Коллекции должны поддерживать INotifyCollectionChanged. "

Все объекты зависимости не могут быть сериализованы (Это может затруднить использование ViewModels и DTO (POCO).

Существуют различия между DP в Silverlight по сравнению с WPF.

http://msdn.microsoft.com/en-us/library/cc221408(v=VS.95).aspx

http://msdn.microsoft.com/en-us/library/cc903933(VS.95).aspx

16 голосов
/ 13 февраля 2009

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

DependencyProperty пример:

public static DependencyProperty NameProperty = DependencyProperty.Register( "Name", typeof( String), typeof( Customer ) );

public String Name
{
    set { SetValue( NameProperty, value ); }
    get { return ( String ) GetValue( NameProperty ); }
}

В вашем getter и setter --- все, что вы можете сделать, это просто вызвать SetValue и GetValue соответственно, b / c, в других частях фреймворка getter / setter не вызывается, вместо этого он напрямую вызывает SetValue, GetValue, так что ваш логика свойств не может быть надежно выполнена.

С помощью INotifyPropertyChanged определите событие:

public event PropertyChangedEventHandler PropertyChanged;

А потом просто используйте любую логику в любом месте вашего кода, затем позвоните:

// ...
// Something cool...
// ...

if( this.PropertyChanged != null )
{
    PropertyChanged( this, new PropertyChangedEventArgs( "Name" ) );
}

// More cool stuff that will reliably happen...

Это может быть в методе получения / установки или где-либо еще.

7 голосов
/ 24 ноября 2008

Я тоже должен был рассмотреть это решение недавно.

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

С помощью DP вы не можете определить серверную часть, которая хранит состояние самостоятельно. Мне бы пришлось позволить .net кешировать копию каждого элемента состояния, к которому я привязан. Это казалось ненужными накладными расходами - мое состояние большое и сложное.

Итак, я обнаружил, что INotifyPropertyChanged лучше для предоставления свойств бизнес-логики графическому интерфейсу.

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

Таким образом, я обнаружил, что DP полезен для уведомления от GUI к GUI.

6 голосов
/ 15 ноября 2008

Действительно ли хорошая идея передать зависимости ViewModel в WPF?

.NET 4.0 будет иметь System.Xaml.dll, поэтому вам не придется использовать зависимость от произвольной среды для ее использования. См. пост Роба Рельеи о его сессии PDC.

Мой дубль

XAML - это язык для описания объектов, а WPF - это среда, чьи описанные объекты являются элементами пользовательского интерфейса.

Их отношения похожи на C #, язык для описания логики, и .NET, каркас, который реализует определенные виды логики.

Цель XAML - декларативные графы объектов. Технологии W * F являются отличными кандидатами на эту парадигму, но XAML существует независимо от них.

XAML и вся система зависимостей были реализованы в виде отдельных стеков для WF и WPF, возможно, для использования опыта различных команд без создания зависимости (без каламбура) между ними.

5 голосов
/ 29 октября 2014

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

4 голосов
/ 02 сентября 2010

Я думаю, что DependencyProperty и INotifyPropertyChanged используются для двух разных вещей в Binding: первое - для того, чтобы свойство могло быть целью привязки и получать входные данные из другого свойства (используйте {Binding ...} для установки свойства) последний, когда вы хотите, чтобы значение свойства использовалось в качестве источника привязки (имя в выражении пути привязки). Так что выбор чисто технический.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...