Свойства за обвиване в съвместими с WPF свойства за прилагане на INotifyPropertyChanged

В моето WPF приложение моят Model клас наследява от клас ParentClass като такъв:

Model : ParentClass, INotifyPropertyChanged

Приложението ми просто има за цел да предостави потребителски интерфейс за тестване и валидиране на ParentClass. Така че Model наистина не е много повече от INotifyPropertyChanged реализация, поставена върху ParentClass

Въпреки това все още трябва да имам достъп до данните от този родителски клас и той да отговаря на потребителския интерфейс.

Ако приемем, че Slicing е свойство в ParentClass, а WPFSlicing е свойство в Model, ето как го правя в момента. Обгръщам всяко родителско свойство в свойство, съвместимо с WPF.

public Thickness WPFSlicing
{
    get { return Slicing; }
    set
    {
        Slicing = value;
        OnPropertyChanged("Slicing");
    }
}

Има ли по-умен начин да направите това? Имам много свойства в моя родителски клас и това изглежда като много невдъхновен метод.


person William Thomas Waller    schedule 13.08.2014    source източник
comment
Да, трябва да извикате OnPropertyChanged(propertyName) за всеки сетер :(   -  person Jon    schedule 13.08.2014
comment
Изглежда, че нямате добро разделение за View, Model и ViewModel. Може би можете да редактирате въпроса си, за да покажете кой от вашите класове съответства на кой от домейните на MVVM.   -  person Mare Infinitus    schedule 13.08.2014
comment
Не е ли обичайно внедряването на INotifyPropertyChanged в модела?   -  person William Thomas Waller    schedule 13.08.2014
comment
ще ви трябва. Но може би вие търсите това. msdn.microsoft.com/en-us/library/ms165394.aspx   -  person Core-One    schedule 13.08.2014
comment
Не съм сигурен как тази връзка е уместна, @Core-One   -  person William Thomas Waller    schedule 13.08.2014
comment
Ако вашата версия на VS поддържа макроси (или алтернативи на макроси), намирам за най-бързо просто да запиша макрос, който ще запише всички неща за промяна на собствеността за мен. Имам пример тук, ако проявявате интерес.   -  person Rachel    schedule 13.08.2014
comment
Ако вашият модел има свойства от тип Thickness и други подобни специфични за потребителския интерфейс типове, тогава вие не сте наистина MVVMing и затова правете каквото искате - няма значение.   -  person    schedule 13.08.2014
comment
ParentClass са рендируеми данни за използване извън моето приложение. В контекста на моето приложение това все още са само данни за модела.   -  person William Thomas Waller    schedule 13.08.2014


Отговори (2)


Това е много интересен въпрос.

Обикновено открих, че в приложенията на MVVM се опитвате да изолирате модел като краен резултат -- продукт/част от данни -- на View Model. Ако трябваше да имате магазин за велосипеди, например, ще видите витрината като изгледа, продавача като модела на изгледа (ако приемем, че това е велосипед с възможност за персонализиране, който е създаден по поръчка), а модела като завършен обект на велосипед.

В случай на изграждане на велосипеда, докато е в етап на "прототипиране", който трябва да бъде представен, имам склонност да го увия в ViewModel - защото има логика в него. Изглежда като допълнителна стъпка, но в крайна сметка можете да имате валидации в този ViewModel, докато го конструирате. Ако вашият модел е негъвкав за добавяне на INotifyPropertyChanged към него (или ако е генериран от услуга), ще имате проблеми, ако имате "0" гуми на велосипеда -- това трябва да създаде проблеми!

Много хора са склонни да стават малко по-мързеливи и да виждат MVVM като модел, който абстрахира прототипни модели (където въвеждането на данни се връща напред/назад, актуализира се) към модели - когато те всъщност трябва да бъдат ViewModels.

Според примера бих имал MVVM директория, която изглежда така:

Models
  -Bicycle (an object that can be passed across a service, etc -- data)
Views
  -BicycleCreatorView (the view or data template of the model)
  -StoreFrontView (the view of the entire store/app)
ViewModels
  -BicycleCreatorViewModel (the view model which CONSTRUCTS a Bicycle model as the end     result)
  -StoreFrontViewModel (the view model for the entire store)

Сега можете много лесно СЪЩО да накарате BicycleCreatorViewModel да има конструктор, който приема модел на велосипед и предварително попълва. Това не е необичайно. Някой може да влезе в магазин и да каже: "Хей, можеш ли да направиш това подобно на другото? Ето как изглежда." Въпреки че крайният резултат е да имаме друго свойство (вероятно просто get {}), което всъщност изобразява обект Bicycle, АКО валидирането е добро и нямаме нещо необичайно с 0 гуми, без седалка (може би това е функция?) и т.н.

И така, накратко -- винаги бих искал вашият модел (ако не можете да го разширите по НИКАКЪВ начин) да бъде обвит в негов СОБСТВЕН ViewModel за тази цел. Това би бил истинският MVVM модел. Винаги можете да използвате неща като ReactiveUI или други инструменти, които могат да обгръщат свойствата. Може да отделите малко повече време за това, но крайният продукт ще бъде много по-гъвкав и по-малко податлив на грешки от друг. По същество вие вече правите това, но вероятно бихте могли да го пренапишете, така че да изглежда "по-чисто" и да има начертана линия.

На теория можете също да проверите дали можете да подходите към него по метод като този:

Има ли аспектно ориентиран инструментариум, който бихте могли да използвате потенциално? Може би да направите вашите класове частични, за да включите INotifyPropertyChanged в разширението и след това XmlIgnore определени части, ако сериализацията е проблем/въпрос?

Проблемът е, че имаме много малко познания за това откъде идва моделът и как го използвате. Надявам се това да ви помогне или да ви даде интересна идея. Ще се радвам да видя дали предлагате решение, което е по-„вдъхновено“ от стандартното.

person Locke    schedule 13.08.2014
comment
Благодаря за дългия отговор! Всъщност дори не мислех за Model като ViewModel за ParentClass, но сега, като се замислих за това, наистина е това, което е. - person William Thomas Waller; 13.08.2014

Предлагам алтернативен изглед. Всичко това може да бъде изключително просто решено с AOP framework, като PostSharp. Всичко, което правите, е да прикачите атрибута [NotifyPropertyChanged] към вашия клас и вашият модел има всичко свързано.

http://www.postsharp.net/aspects/examples/inotifypropertychanged

Бъдете предупредени обаче, струва, но може да бъде добра инвестиция, imo.

Ps, това е въпрос на гледна точка, но не виждам нищо лошо в това всички класове на модели на DOMAIN да прилагат INotifyPropertyChanged. Това не убива производителността, единственият недостатък е, че малко претрупва кода. Това е, което направих, моите обекти на модел на домейн се внедряват от CommonEntity и INotifyPropertyChanged. INotifyPropertyChanged не е част от WPF!

Работи и определено е по-приятно от обгръщането на моделите ви в изгледи.

person Erti-Chris Eelmaa    schedule 13.08.2014
comment
Всъщност съм просто стажант и ParentClass е клас, който би накарал хората много да се ядосат, ако ги докосна хаха. В противен случай със сигурност бих разгледал ParentClass прилагането на INotifyPropertyChanged - person William Thomas Waller; 13.08.2014
comment
Харесвам това решение за AOP, но ако договорът ви е заключен, не можете просто да украсите договора с етикет. Съгласен съм, че AOP предоставя много страхотна функционалност, но ако сте заключени, че вашият модел идва от нещо извън вашия контрол (да речем DLL на комуникационния слой с договори), единственият реален избор е да изградите нещо. Но вместо въпроса, горният отговор е интересен начин да избегнете необходимостта да пишете всички допълнителни извиквания OnNotifyPropertyChanged и т.н. - person Locke; 14.08.2014