Основні поняття MVVM - що повинен робити ViewModel?


83

Намагаючись зрозуміти концепції MVVM, я вже прочитав декілька блогів і переглянув кілька проектів.

Наскільки я розумію, Погляд німий, він просто знає, як представити щось, що йому передано.

Моделі - це просто прості дані, а ViewModel - це щось, що діє як прокладка між ними, що воно повинно отримувати інформацію від Моделі та передавати її у View , а View повинен знати, як її представити. Або навпаки, якщо інформація у поданні змінюється, вона повинна передати зміни до Моделі .

Але я досі не уявляю, як застосувати цю концепцію. Хтось може пояснити дуже простий сценарій, щоб я міг зрозуміти концепцію? Я вже переглядав декілька проектів, але все одно це не має повного сенсу, тож, якщо хтось може написати це простою англійською, це було б непогано.


2
Не можу погодитися із твердженням, що погляд "просто знати, як представити щось, що йому передано.". Перегляд бере дані з ВМ. До нього ніхто не передає дані. Про вигляд ніхто не знає. Це важлива відмінність від MVP. У MVP (ви можете думати про це як про простий додаток WPF з логікою codebehind, це шаблон MVP) codebehind - це презентатор, який передає дані у View, як ви сказали.
Григорій

Відповіді:


146

Мені подобається думати про це так:

Погляди, як ти кажеш, німі. Джош Сміт, письменник основної статті, на яку часто посилається стаття MSDN про MVVM, заявив, що погляди - це "одяг, який носять дані". Представлення фактично ніколи не містять даних або безпосередньо ними не маніпулюють, вони просто пов'язані з властивостями та командами ваших моделей перегляду.

Моделі - це об’єкти, що моделюють домен вашої програми , як у бізнес-об’єктах. Ваша програма є музичним магазином? Можливо, вашими модельними об'єктами будуть виконавці, альбоми та пісні. Ваша програма є орг-діаграмою? Можливо, об'єктами вашої моделі будуть менеджери та співробітники. Ці об’єкти моделі не пов’язані з будь-яким візуальним візуалізацією і навіть не пов’язані безпосередньо з додатком, в який ви їх розміщуєте - об’єкти моделі повинні мати сенс повністю самостійно як сімейство об’єктів, що представляють певний домену. Рівень моделі також зазвичай включає такі речі, як доступ до послуг.

Це призводить до Viewmodels. Хто вони? Вони є об'єктами, що моделюють програму графічного інтерфейсу, тобто вони надають дані та функціональні можливості, які будуть використовуватися поданнями. Саме вони визначають структуру та поведінку фактичного додатка, який ви створюєте. Для об'єктів моделі домен - це будь-який вибраний вами домен (музичний магазин, браузер організаційних діаграм тощо), але для моделі перегляду домен є графічним додатком. Моделі перегляду збираються інкапсулювати поведінку та дані всього, що робить ваша програма. Вони збираються виставити об'єкти та списки як властивості, а також такі речі, як команди. Команда - це просто поведінка (найпростіший - виклик методу), обгорнута в об’єкт, який її переносить - ця ідея важлива, оскільки подання керуються прив’язкою даних, яка прикріплює візуальні елементи керування до об’єктів. У MVVM ви не надаєте кнопці метод обробника кліків,

Для мене найбільш заплутаними бітами були такі:

  • Незважаючи на те, що моделі перегляду є моделями графічного додатка, вони безпосередньо не посилаються і не використовують візуальні концепції. Наприклад, ви не хочете посилання на елементи керування Windows у ваших ViewModels - ці речі йдуть у поданні. ViewModels просто піддають дані та поведінку елементам керування або іншим об’єктам, які зв’язуються з ними. Наприклад - у вас є подання з ListBox? У вашій viewmodel майже напевно буде якась колекція. У вашому поданні є кнопки? У вашій viewmodel майже напевно будуть деякі команди.
  • Існує кілька видів об’єктів, які можна вважати „моделями перегляду”. Найпростіший тип viewmodel для розуміння - це той, який безпосередньо представляє елемент керування або екран у співвідношенні 1: 1, як у "screen XYZ має текстове поле, список і три кнопки, тому viewmodel потребує рядок, колекцію, і три команди ". Інший тип об’єкта, який поміщається в шар viewmodel, - це обгортка навколо об’єкта моделі, яка надає йому поведінку та робить його більш корисним для подання - тут ви потрапляєте в поняття «товстий» та «тонкий» шари viewmodel. "Тонкий" шар viewmodel - це набір моделей перегляду, які виставляють об'єкти вашої моделі безпосередньо на представлення, тобто перегляди в кінцевому підсумку прив'язуються безпосередньо до властивостей об'єктів моделі. Це може працювати для таких речей, як прості подання лише для читання, але що, якщо ви хочете мати поведінку, пов’язану з кожним об’єктом? Ви не хочете цього в моделі, оскільки модель не пов’язана з додатком, вона пов’язана лише з вашим доменом. Ви можете помістити його в об'єкт, який обертає об'єкт вашої моделі та пропонує більш зручні дані та поведінку. Цей об'єкт-обгортка також вважається моделью перегляду, і їх отримання призводить до "товстішого" шару моделі перегляду, де ваші погляди ніколи не закінчуються безпосереднім прив'язуванням до чогось у класі моделі. Колекції будуть містити моделі перегляду, які обертають моделі, а не просто містять самі моделі. Ви можете помістити його в об'єкт, який обертає об'єкт вашої моделі та пропонує більш зручні дані та поведінку. Цей об'єкт-обгортка також вважається моделью перегляду, і їх отримання призводить до "товстішого" шару моделі перегляду, де ваші погляди ніколи не закінчуються безпосереднім прив'язуванням до чогось у класі моделі. Колекції будуть містити моделі перегляду, які обертають моделі, а не просто містять самі моделі. Ви можете помістити його в об'єкт, який обертає об'єкт вашої моделі та пропонує більш зручні дані та поведінку. Цей об'єкт-обгортка також вважається моделью перегляду, і їх отримання призводить до "товстішого" шару моделі перегляду, де ваші погляди ніколи не закінчуються безпосереднім прив'язуванням до чогось у класі моделі. Колекції будуть містити моделі перегляду, які обертають моделі, а не просто містять самі моделі.

Кроляча діра заглиблюється - існує безліч ідіом, щоб зрозуміти, як ValueConverters, які підтримують роботу MVVM, і є багато чого застосувати, коли ви починаєте думати про такі речі, як сумісність, тестування та про те, як передавати дані у своєму додатку та гарантувати, що кожна модель перегляду має доступ до поведінки, яка їй потрібна (саме тут входить ін’єкція залежностей), але, сподіваємось, вищесказане є хорошим початком. Головне - думати про свої візуальні ефекти, домен, структуру та поведінку вашого фактичного додатку як про три різні речі.


3
+1 - Я опинився тут, тому що мене збентежила "обгортка" ViewModel, яка зустрічається у зразку коду. Дякую за
роз'яснення

1
Чудова відповідь - хотілося б, щоб я міг +10.
Нік Ходжес

1
@nlawalker Дуже приголомшливо! Подвійні біти u, коментар вище, бентежать мене дуже довго. Багато статей та блогів розповідають лише про "ключові особливості" MVVM, але коли ти намагаєшся з цим розібратися, речі починають бути дуже складними ! Наприклад, "Як орієнтуватися в цих поданнях?" "Яка відповідна деталізація при розробці ViewModels?" "Чи повинен View мати відповідний ViewModel, чи один ViewModel може бути використаний повторно в різних поданнях?" Ваше роз'яснення щодо ViewModel, складене за допомогою "Slim VM" і "Thick VM", справді має сенс! Я намагаюся, це працює добре, тому далеко! :)
Claw

@nlawalker Дякую! І ще одне запитання: у мене є treeView і я роблю TreeViewViewModel. Отже, якщо я створю в методі ViewModel такі методи, як: ExpandTree (). Чи правильно?
user2545071

Ого, це відмінна стаття, досить гарна робота @nlawalker
Вівек Шукла

25

Використовуючи цю неймовірно корисну статтю як джерело, ось короткий зміст для View , ViewModel та Model .


Вид:

  • Вигляд - це візуальний елемент, такий як вікно, сторінка, елемент керування користувача або шаблон даних. Вигляд визначає елементи керування, що містяться у поданні, а також їх візуальний макет та стиль.

  • Подання посилається на модель перегляду через її DataContextвластивість. Елементи керування у поданні - це дані, прив’язані до властивостей та команд, що виставляються моделлю подання.

  • Представлення даних може налаштувати поведінку прив'язки даних між видом та моделлю подання. Наприклад, подання може використовувати перетворювачі значень для форматування даних, що відображаються в інтерфейсі користувача, або може використовувати правила перевірки, щоб забезпечити додаткову перевірку вхідних даних для користувача.

  • Представлення визначає та обробляє візуальну поведінку інтерфейсу користувача, наприклад анімацію або переходи, які можуть бути викликані зміною стану у моделі подання або через взаємодію користувача з інтерфейсом користувача.

  • Закритий код подання може визначати логіку інтерфейсу для реалізації візуальної поведінки, яку важко виразити в XAML або яка вимагає прямих посилань на конкретні елементи керування інтерфейсом, визначені у поданні.

ПРИМІТКА:
Оскільки модель подання не повинна чітко знати конкретні візуальні елементи у поданні, код для програмного маніпулювання візуальними елементами у поданні повинен знаходитися в коді подання або бути інкапсульований у поведінці.


Модель перегляду:

  • Модель подання є невізуальним класом і не походить від будь-якого базового класу WPF або Silverlight. Він інкапсулює логіку презентації, необхідну для підтримки випадку використання або завдання користувача в додатку. Модель подання перевіряється незалежно від виду та моделі.

  • Модель подання, як правило, не посилається безпосередньо на вигляд. Він реалізує властивості та команди, до яких подання може прив'язувати дані. Він повідомляє про перегляд будь-яких змін стану за допомогою повідомлень про зміни через інтерфейси INotifyPropertyChangedта та INotifyCollectionChanged.

  • Модель подання координує взаємодію виду з моделлю. Він може перетворювати дані або маніпулювати ними, щоб їх можна було легко використовувати в поданні, і може реалізовувати додаткові властивості, які можуть не бути присутніми на моделі. Він також може реалізувати перевірку даних через інтерфейси IDataErrorInfoабо INotifyDataErrorInfo.

  • Модель перегляду може визначати логічні стани, які подання може візуально представляти для користувача.

ПРИМІТКА.
Усе, що є важливим для логічної поведінки програми, повинно входити в модель подання. Код для отримання або керування елементами даних, які повинні відображатися у поданні за допомогою прив'язки даних, повинен міститися в моделі подання.


Модель:

  • Класи моделей - це невізуальні класи, які інкапсулюють дані програми та бізнес-логіку. Вони відповідають за управління даними програми та за забезпечення їх послідовності та обгрунтованості шляхом інкапсуляції необхідних бізнес-правил та логіки перевірки даних.

  • Класи моделі безпосередньо не посилаються на класи подання або класи моделі та не мають залежності від того, як вони реалізовані.

  • Класи моделі зазвичай надають властивості та події сповіщень про зміни колекції через інтерфейси INotifyPropertyChangedі INotifyCollectionChanged. Це дозволяє їм легко зв’язувати дані у поданні. Класи моделей, що представляють колекції об'єктів, як правило, походять від ObservableCollection<T>класу.

  • Класи моделі зазвичай забезпечують перевірку даних та звітування про помилки через інтерфейси IDataErrorInfoабо INotifyDataErrorInfo.

  • Класи моделей, як правило, використовуються разом із службою або сховищем, яке інкапсулює доступ до даних та кешування.


17

Я написав це приблизно таким "простим англійським", як я можу думати в цій серії на MVVM . Зокрема, ця діаграма є, мабуть, найпростішим, коротким поясненням.

При цьому, в основному, "моделлю" є ваші дані або ділові правила. Насправді він не повинен знати про те, як і де він буде використовуватися, і особливо не про те, яка технологія його буде використовувати. "Модель" - це основна кішка програми - і не слід турбуватися про те, чи є програма WPF, Silverlight, Windows Forms, ASP.NET тощо - це просто "сама" у чистому вигляді.

"Погляд" - це частина, яка повністю відповідає технологіям. У MVVM, в ідеалі, View повинен складати майже 100% XAML, оскільки це забезпечує величезні вигоди для гнучкості.

Однак, повинно бути щось, що перетворює інформацію з Моделі в певну форму, де вона може бути використана відповідною технологією - саме тут входить у дію ViewModel. Наприклад, це часто "обертає" класи моделей у "ViewModel" для тих конкретних даних, які включають команди (для запуску логіки), реалізації INotifyPropertyChanged(для підтримки прив'язки даних) тощо. Ось і все - це міст, який робить модель доступний для перегляду.


Добре, дякую. Я розглядав Модель як об'єкти, а ViewModel як методи обробки об'єктів, такі, що подання може зрозуміти "об'єкти" Моделі. Але мені сказали, що це неправильно, що сам ViewModel теж є об’єктами. Думаю, саме це мене дійсно бентежить.
RKM

@Rosie: Я б рекомендував прочитати (або, принаймні, скремінг) мою цитату, яку я цитував. Я написав це спеціально, тому що є мало (майже немає) статей про MVVM, які вже не припускають, що ви розумієте MVC чи MVP тощо. Це справді перехід "поетапно";)
Рід Копсі,

Розуміючи, що це трохи зомбі-потоків ... На вашій схемі написано, що віртуальна машина містить "специфічний для програми стан і логіку " (моя emph). Чи припускає це, що ви думаєте, що віртуальна машина могла / повинна містити логіку контролю якості даних? Схоже, RssWpfMVVM.csproj, здається, не має жодної очевидної якості в двох своїх моделях перегляду.
jorffin

1

Чудове вступ до MVVM можна знайти у відео Джейсона Долінгера тут . Я тримав відео при собі досить довгий час, коли починав, це справді корисно.


1
Посилання мертве
Ібрагім Махрір

1
@ibrahimmahrir ~ Я оновив посилання на робочу URL-адресу. Зараз завантажую відео.
InteXX

0

Побудова ViewModel, яка представляє послідовний фасад над базовою Моделью, може бути набагато складнішою, ніж здається. Ця стаття про побудову об’єктів ViewModel демонструє, як створити ViewModel, та ілюструє деякі проблеми, з якими ви, мабуть, зіткнетесь, а також те, що виглядає як розумні рішення. Коли я прочитав його, розділ, присвячений роботі з колекціями, відсутній, але він все одно має деякі цікаві моменти.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.