Використання модуля подання
- 8 хв.
Дізнавшись про компоненти, які складають шаблон Model-View-ViewModel (MVVM), ви, напевно, виявили, що модель і подання було легко визначити. Розгляньмо, як використовувати viewmodel, щоб краще визначити його роль у шаблоні.
Відображення властивостей інтерфейсу користувача
Як і в попередньому прикладі, viewmodels зазвичай використовують моделі для більшості своїх даних і будь-якої бізнес-логіки. Але це подання, яке форматує, перетворює та збагачує дані в будь-який спосіб, який вимагає поточне подання.
Форматування за допомогою viewmodel
Ви вже побачили приклад форматування з часом відпустки. Форматування дати, кодування символів і серіалізація – це всі приклади того, як viewmodel може форматувати дані з моделі.
Перетворення за допомогою viewmodel
Часто модель надає інформацію непрямими способами. Але viewmodel може виправити це. Припустімо, наприклад, що потрібно показати на екрані, чи є працівник керівником. Але наша модель Employee не говорить нам, що безпосередньо. Замість цього ви повинні припустити цей факт, виходячи з того, чи є в людини інші повідомляють про них. Припустімо, що модель має цю властивість:
public IList<Employee> DirectReports
{
get
{
...
}
}
Якщо список пустий, можна припустити, що цей Employee не є керівником. У цьому випадку EmployeeViewModel включає властивість IsSupervisor, яка надає таку логіку:
public bool IsSupervisor => _model.DirectReports.Any();
Збагачення за допомогою viewmodel
Іноді модель може надавати лише ідентифікатор пов'язаних даних. Або, можливо, знадобиться перейти до кількох класів моделей, щоб зв'язувати дані, необхідні для одного екрана. Viewmodel – це ідеальне місце для виконання цих завдань. Припустімо, що потрібно відобразити всі проекти, якими зараз керує працівник. Ці дані не входять до класу моделі Employee. Доступ до нього можна отримати, переглянувши клас моделі CompanyProjects. Наша EmployeeViewModel, як завжди, викриває свою роботу як державну власність:
public IEnumerable<string> ActiveProjects => CompanyProjects.All
.Where(p => p.Owner == _model.Id && p.IsActive)
.Select(p => p.Name);
Використання прохідних властивостей із модельним поданням
Часто для перегляду потрібно точно властивість, яку надає модель. Для цих властивостей viewmodel просто передає дані через:
public string Name
{
get => _model.Name;
set => _model.Name = value;
}
Установлення області перегляду
Ви можете використовувати viewmodel на будь-якому рівні, де є подання. Зазвичай сторінка подання, але так можуть відображатися підперегляди сторінки. Одна з поширених причин вкладених моделях подання полягає в тому, що на сторінці відображається CollectionView. Список має вигляд колекції, наприклад EmployeeListViewModel. Кожен елемент списку – це EmployeeViewModel.
Крім того, зазвичай є модуль перегляду верхнього рівня, який містить дані та стан для всього застосунку, але не пов'язаний із певною сторінкою. Такий viewmodel зазвичай використовується для збереження "активного" елемента. Розглянемо CollectionView приклад, який ми щойно описали. Коли користувач вибирає рядок працівника, цей працівник представляє поточний елемент. Якщо користувач переходить на сторінку відомостей або вибирає кнопку панелі інструментів під час вибору цього рядка, дія або відображення має відображатися для цього працівника. Елегантний спосіб обробки цього сценарію – прив'язати CollectionView.SelectedItem даних до властивості, до яких також може отримати доступ панель інструментів або сторінка відомостей. Розміщення цієї властивості на центральному видімодель працює добре.
Визначення випадків повторного використання viewmodels з поданнями
Спосіб визначення зв'язку між viewmodel і моделлю, а також між viewmodel і view, визначається більше вимогами програми, ніж правилами. Мета viewmodel полягає в тому, щоб надати для перегляду структуру та дані, які йому потрібні. Ця мета повинна скерувати рішення про те, "наскільки великий" для масштабування viewmodel.
Viewmodels часто тісно відображають структуру модельного класу, і вони мають зв'язок "один-до-одного" з цим класом. Ви бачили приклад раніше з EmployeeViewModel, які обтікання та збільшення одного екземпляра Employee. Але це не завжди зв'язок "один-до-одного". Якщо viewmodel призначено для надання потрібних даних у поданні, натомість може виникнути щось на кшталт HRDashboardViewModel, щоб переглянути відділ кадрів, який не має явного відношення до будь-якої моделі, але може використовувати дані з будь-якого класу моделі.
Аналогічно, ви можете виявити, що подання та подання часто мають зв'язок "один-до-одного". Але не завжди. Давайте знову розглянемо CollectionView з рядком для кожного працівника. Якщо вибрати один із рядків, перейдіть на сторінку відомостей про працівників.
Сторінка списку має свій видмодель з колекцією. Як було запропоновано раніше, колекції може бути колекцією EmployeeViewModel об'єктів. Коли користувач вибирає рядок, екземпляр EmployeeViewModel може передаватися до EmployeeDetailPage. І сторінка відомостей може використовувати цю EmployeeViewModel як BindingContext.
Цей сценарій може бути відмінною можливістю для повторного використання viewmodel. Але майте на увазі, що viewmodels призначені для забезпечення того, що подання потребує. У деяких випадках можуть знадобитися окремі модулювання, навіть якщо всі вони засновані на одному класі моделі. У цьому прикладі рядки CollectionView, швидше за все, потребують набагато менше інформації, ніж на сторінці з повними відомостями. Якщо отримання даних із сторінки відомостей додає забагато накладних витрат, можливо, знадобиться мати моделі EmployeeListRowViewModel та EmployeeDetailViewModel, які обслуговують ці відповідні подання.
Об'єктна модель Viewmodel
Використання базового класу, який впроваджує INotifyPropertyChanged, означає, що вам не потрібно повторно вимикати інтерфейс у кожному viewmodel. Розглянемо hr-програму, як описано в попередній частині цього навчального модуля. Клас EmployeeViewModel реалізував інтерфейс INotifyPropertyChanged і надав допоміжний метод під назвою OnPropertyChanged, щоб підняти подію PropertyChanged. Інші подання в проекті, як-от ресурси, призначені працівнику, також потребуватимуть INotifyPropertyChanged для повної інтеграції з поданням.
Бібліотека MVVM Toolkit, що входить до складу інструментів спільноти .NET, – це колекція стандартних, автономних, легких типів, які забезпечують початкове впровадження для створення сучасних програм за допомогою шаблону MVVM.
Замість того, щоб писати власний базовий клас viewmodel, ви успадковуєте від класу ObservableObject інструментів, який надає все необхідне для базового класу viewmodel.
EmployeeViewModel можна спростити з:
using System.ComponentModel;
public class EmployeeViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
private Employee _model;
public string Name
{
get {...}
set
{
_model.Name = value;
OnPropertyChanged(nameof(Name))
}
}
protected void OnPropertyChanged(string propertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
До такого коду:
using Microsoft.Toolkit.Mvvm.ComponentModel;
public class EmployeeViewModel : ObservableObject
{
private string _name;
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
}
Код можна додатково спростити за допомогою генераторів джерел, наданих засобом MVVM Toolkit. Щоб зробити клас partial та додати [ObservableProperty] до змінної private, Name загальнодоступної властивості створюється з відповідними сповіщеннями про змінення властивостей.
using Microsoft.Toolkit.Mvvm.ComponentModel;
public partial class EmployeeViewModel : ObservableObject
{
[ObservableProperty]
private string _name;
}
Засіб MVVM розповсюджується через пакет CommunityToolkit.Mvvm NuGet.