2008-11-14 2 views
331

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

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

+5

Может ли кто-то изменить опечатку «DependencyPropterty» на «DependencyProperty»? – Sung 2009-02-22 06:04:12

+10

см. Http://stackoverflow.com/questions/1329138/how-to-make-databinding-type-safe-and-support-refactoring/1333874#1333874 для компилятора проверенного способа реализации INotifyPropertyChanged. Избегайте наличия имен свойств в качестве магической строки. – 2009-08-26 11:57:32

+9

Как правило, существует основное различие между свойством зависимости и нормальным свойством в классе, который реализует INotifyPropertyChanged. Свойства зависимостей могут быть исходными или целевыми в привязке данных, но нормальные свойства с поддержкой INotifyPropertyChanged могут использоваться только как исходные. Таким образом, эти решения не являются полностью взаимозаменяемыми. Для инфраструктуры привязки данных требуется, чтобы DP был предназначен для работы, но источник может быть либо нормальным свойством с поддержкой INotifyPropertyChanged, либо общим DP. – 2011-08-26 19:37:48

ответ

202

Kent написал интересный блог об этой теме: View Models: POCOs versus DependencyObjects.

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

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

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

26

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

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

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

+9

Сообщение jbe отвечает на различия более точно. Просто потому, что VM (или Presenter) наследуется от DependencyObject, не означает, что он не может быть стилизован или не логически отделен от представления, это просто означает, что хранилище для значений свойств отличается от явно объявленных полей в Стиль POCO. Это означает, что сериализация, логическое равенство и сродство потоков являются реальными проблемами, с которыми приходится сталкиваться виртуальным машинам на основе DepedencyObject. – micahtan 2009-05-25 19:38:43

+0

I второе мнение о михайтане на jbe ответ. – 2009-06-21 07:18:39

+0

ссылка мертва, пожалуйста, обновите ее – Maslow 2016-01-18 16:11:09

6

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

У .NET 4.0 будет файл System.Xaml.dll, поэтому вам не придется зависеть от произвольной структуры, чтобы использовать его. См. Rob Relyea's сообщение о его сеансе PDC.

Мои принять

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

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

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

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

+0

Отвечая, вы, кажется, делаете предположение, что bitbonk считает XAML и WPF одинаковыми. ViewModels должен иметь как можно меньше зависимостей WPF, а не увеличивать логическое разделение, а также уменьшать сложность кода и избегать всех проблем, связанных с простой записью логики в коде кода пользователя. Вы неизбежно внедряете концепции WPF, такие как ICommand, и поведение, которое может легко переносить только WPF/Silverlight - ваши единственные проблемы с потоками представления в модели представления должны быть CollectionViews и ObservableCollection. – Gusdor 2011-06-13 11:00:00

19

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

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

+1

Теперь часть строки имеет решение с именем оператора. – Newtopian 2017-05-30 14:03:03

7

Мне тоже пришлось рассмотреть это решение недавно.

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

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

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

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

Итак, я нашел, что DP полезен для GUI для уведомления GUI.

3

Я предпочитаю более прямой подход, о котором я писал в Presentation Model Without INotifyPropertyChanged. Используя альтернативу привязке данных, вы можете напрямую привязываться к свойствам CLR без кода бухгалтерского учета. Вы просто пишете простой текстовый код .NET в своей модели просмотра, и он обновляется при изменении вашей модели данных.

16

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); } 
} 

В вашем геттер и сеттер --- все, что вы можете сделать, это просто вызвать SetValue и GetValue, соответственно, б/с в других частях рамок-газопоглотитель/сеттер не называется , вместо этого он напрямую вызывает 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... 

Это может быть в геттер/сеттер, или где-нибудь остальное.

4

Кажется, что свойства зависимостей должны использоваться в элементах управления, которые вы создаете, таких как кнопки. Чтобы использовать свойства в XAML и использовать все функции WPF, эти свойства должны иметь свойства зависимостей.

Однако ваш ViewModel лучше использовать INotifyPropertyChanged. Использование INotifyPropertyChanged даст вам возможность иметь логику getter/setter, если вам нужно.

Я рекомендую проверить версию Josh Смита базовый класс для ViewModel, который уже реализует INotifyPropertyChanged:

http://joshsmithonwpf.wordpress.com/2007/08/29/a-base-class-which-implements-inotifypropertychanged/

Я думаю, что это отличный пример того, как сделать ViewModel.

4

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

1

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

3

Есть только одна вещь, почему нужно предпочесть DependencyObject - Связывание будет работать лучше. Просто попробуйте пример с ListBox и TextBox, заполнить список с данными из INotifyPropertyChanged собственности VS. DependencyProperty и редактировать текущий элемент из TextBox ...

15

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

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

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

Существуют различия между 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

4

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