Použití modelu viewmodel
Po seznámení s komponentami, které tvoří model Model-View-ViewModel (MVVM), pravděpodobně jste zjistili, že model a zobrazení byly snadno definovat. Pojďme se podívat, jak model viewmodel používat, abychom lépe definovali jeho roli v modelu.
Zveřejnění vlastností pro uživatelské rozhraní
Stejně jako v předchozím příkladu se modely zobrazení obvykle spoléhají na modely pro většinu dat a jakoukoli obchodní logiku. Jedná se ale o model zobrazení, který formátuje, převádí a rozšiřuje data jakýmkoli způsobem, který aktuální zobrazení vyžaduje.
Formátování pomocí modelu viewmodel
Už jste viděli příklad formátování pomocí dovolené. Formátování data, kódování znaků a serializace jsou všechny příklady, jak model viewmodel může formátovat data z modelu.
Převod pomocí modelu viewmodel
Model často poskytuje informace nepřímými způsoby. Ale model viewmodel to dokáže opravit. Předpokládejme například, že chcete zobrazit na obrazovce, jestli je zaměstnanec nadřízený. Ale náš Employee
model nám to přímo neřekne. Místo toho musíte tuto skutečnost odvodit na základě toho, jestli má tato osoba jiné hlášení. Předpokládejme, že model má tuto vlastnost:
public IList<Employee> DirectReports
{
get
{
...
}
}
Pokud je seznam prázdný, můžete odvodit, že to Employee
není nadřízený. V tomto případě zahrnuje vlastnostIsSupervisor
, EmployeeViewModel
která poskytuje tuto logiku:
public bool IsSupervisor => _model.DirectReports.Any();
Rozšíření pomocí modelu viewmodel
Někdy může model poskytnout pouze ID pro související data. Nebo možná budete muset přejít na několik tříd modelů, abyste korelovaly data potřebná pro jednu obrazovku. Model viewmodel poskytuje ideální místo pro provádění těchto úloh. Předpokládejme, že chcete zobrazit všechny projekty, které právě spravuje zaměstnanec. Tato data nejsou součástí Employee
třídy modelu. Přístup k němu získáte tak, že se podíváte na CompanyProjects
třídu modelu. Naše EmployeeViewModel
, jako vždy, zveřejňuje svou práci jako veřejný majetek:
public IEnumerable<string> ActiveProjects => CompanyProjects.All
.Where(p => p.Owner == _model.Id && p.IsActive)
.Select(p => p.Name);
Použití průchozích vlastností s modelem viewmodel
Model viewmodel často potřebuje přesně vlastnost, kterou model poskytuje. U těchto vlastností model viewmodel právě předává data:
public string Name
{
get => _model.Name;
set => _model.Name = value;
}
Nastavení oboru pro model viewmodel
Model viewmodel můžete použít na libovolné úrovni, kde je zobrazení. Stránka má obvykle model zobrazení, ale může to být i dílčí zobrazení stránky. Jedním z běžných důvodů vnořených modelů zobrazení je, když se na stránce zobrazí ListView
stránka. Seznam obsahuje model zobrazení, který představuje kolekci, například EmployeeListViewModel
. Každý prvek v seznamu je .EmployeeViewModel
Je také běžné mít model zobrazení nejvyšší úrovně, který obsahuje data a stav pro celou aplikaci, ale není přidružen k žádné konkrétní stránce. Takový model zobrazení se běžně používá k údržbě "aktivní" položky. ListView
Představte si příklad, který jsme právě popsali. Když uživatel vybere řádek zaměstnance, představuje tento zaměstnanec aktuální položku. Pokud uživatel přejde na stránku podrobností nebo vybere tlačítko panelu nástrojů při výběru daného řádku, měla by být akce nebo zobrazení určené pro daného zaměstnance. Elegantním způsobem zpracování tohoto scénáře je mít ListView.SelectItem
data svázaná s vlastností, ke které má také přístup panel nástrojů nebo stránka podrobností. Umístění této vlastnosti na centrální viewmodel funguje dobře.
Určení, kdy se mají opakovaně používat modely viewmodelů se zobrazeními
Jak definujete vztah mezi modelem viewmodel a modelem a mezi modelem viewmodel a zobrazením, je diktován více požadavky aplikace než podle pravidel. Účelem modelu viewmodel je poskytnout zobrazení struktury a dat, která potřebuje. Tento účel by měl vést rozhodnutí o tom, jak velký je rozsah modelu zobrazení.
Modely Viewmodels často úzce odrážejí strukturu třídy modelu a mají relaci 1:1 s danou třídou. Viděli jste příklad dříve s EmployeeViewModel
zabalenou a rozšířenou instancí Employee
. Není to ale vždy relace 1:1. Pokud je model viewmodel navržený tak, aby poskytoval to, co zobrazení potřebuje, můžete místo toho vytvořit přehled HRDashboardViewModel
personálního oddělení, které nemá explicitní vztah k žádnému modelu, ale může používat data z libovolné třídy modelu.
Podobně můžete zjistit, že modely zobrazení a zobrazení mají často relaci 1:1. Ale ne vždy. Pojďme se znovu zamyslet nad řádkem ListView
pro každého zaměstnance. Když vyberete jeden z řádků, přejdete na stránku s podrobnostmi o zaměstnancích.
Stránka seznamu má svůj model zobrazení s kolekcí. Jak už bylo navrhnuto dříve, kolekce by mohla být kolekce EmployeeViewModel
objektů. A když uživatel vybere řádek, EmployeeViewModel
může být instance předána do EmployeeDetailPage
. A stránka podrobností by ji mohla použít EmployeeViewModel
jako její BindingContext
.
Tento scénář může být skvělou příležitostí pro opakované použití modelu zobrazení. Mějte ale na paměti, že modely zobrazení mají poskytovat to, co zobrazení potřebuje. V některých případech můžete chtít samostatné modely zobrazení, i když jsou všechny založené na stejné třídě modelu. V tomto příkladu ListView
budou řádky pravděpodobně potřebovat mnohem méně informací než celá stránka podrobností. Pokud načítání dat ze stránky podrobností přidává příliš velkou režii, můžete chtít mít obě EmployeeListRowViewModel
i EmployeeDetailViewModel
modely, které tyto příslušná zobrazení obsluhují.
Model objektu Viewmodel
Použití základní třídy, která implementuje INotifyPropertyChanged
znamená, že nemusíte reimplementovat rozhraní na všech modelech viewmodel. Zvažte aplikaci personálního oddělení, jak je popsáno v předchozí části tohoto školicího modulu. Třída EmployeeViewModel
implementovala INotifyPropertyChanged
rozhraní a poskytla pomocnou metodu pojmenovanou OnPropertyChanged
pro vyvolání PropertyChanged
události. Jiné modely zobrazení v projektu, například ty, které popisují zdroje přiřazené zaměstnanci, by také vyžadovaly INotifyPropertyChanged
úplnou integraci se zobrazením.
Knihovna MVVM Toolkit, která je součástí sady nástrojů .NET Community Toolkit, je kolekce standardních, samostatných jednoduchých typů, které poskytují počáteční implementaci pro vytváření moderních aplikací pomocí vzoru MVVM.
Místo psaní vlastní základní třídy modelu viewmodel zdědíte z třídy sady nástrojů ObservableObject
, která poskytuje vše, co potřebujete pro základní třídu modelu viewmodel. Můžete EmployeeViewModel
ho zjednodušit z následujících důvodů:
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));
}
Na následující kód:
using Microsoft.Toolkit.Mvvm.ComponentModel;
public class EmployeeViewModel : ObservableObject
{
private string _name;
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
}
Kód lze dále zjednodušit pomocí zdrojových generátorů poskytovaných MVVM Toolkit. Když třídu partial
přidáte [ObservableProperty]
do private
proměnné, veřejná vlastnost Name
se vygeneruje s oznámeními o změně příslušné vlastnosti.
using Microsoft.Toolkit.Mvvm.ComponentModel;
public partial class EmployeeViewModel : ObservableObject
{
[ObservableProperty]
private string _name;
}
Sada nástrojů MVVM se distribuuje CommunityToolkit.Mvvm
prostřednictvím balíčku NuGet.