Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
ObservableObject je základní třída pro objekty, které lze pozorovat implementací rozhraní INotifyPropertyChanged a INotifyPropertyChanging. Dá se použít jako výchozí bod pro všechny druhy objektů, které potřebují podporovat oznámení o změnách vlastností.
Rozhraní API platformy:
ObservableObject,TaskNotifierTaskNotifier<T>
Jak to funguje
ObservableObject má následující hlavní funkce:
- Poskytuje základní implementaci pro
INotifyPropertyChangedaINotifyPropertyChanginga zpřístupňuje událostiPropertyChangedaPropertyChanging. - Poskytuje řadu
SetPropertymetod, které lze použít ke snadnému nastavování hodnot vlastností u typů odvozených odObservableObjecta k automatickému vyvolávání příslušných událostí. - Poskytuje metodu
SetPropertyAndNotifyOnCompletion, která je analogickáSetProperty, ale s možností nastavitTaskvlastnosti a vyvolat události oznámení automaticky při dokončení přiřazených úkolů. - Zpřístupňuje metody
OnPropertyChangedaOnPropertyChanging, které lze v odvozených typech přepsat a přizpůsobit tak způsob vyvolávání oznamovacích událostí.
Jednoduchá vlastnost
Tady je příklad implementace podpory oznámení pro vlastní vlastnost:
public class User : ObservableObject
{
private string name;
public string Name
{
get => name;
set => SetProperty(ref name, value);
}
}
Zadaná SetProperty<T>(ref T, T, string) metoda zkontroluje aktuální hodnotu vlastnosti a aktualizuje ji, pokud se liší, a pak také vyvolá příslušné události automaticky. Název vlastnosti se automaticky zaznamenává pomocí atributu [CallerMemberName] , takže není nutné ručně určit, která vlastnost se aktualizuje.
Zabalení nepozorovatelného modelu
Běžným scénářem například při práci s databázovými položkami je vytvoření obalového modelu podporujícího datovou vazbu, který zpřístupňuje vlastnosti databázového modelu a v případě potřeby vyvolává oznámení o změně vlastnosti. To je potřeba také v případě, že chcete do modelů vložit podporu oznámení, která rozhraní neimplementují INotifyPropertyChanged .
ObservableObject poskytuje vyhrazenou metodu, která usnadňuje tento proces. V následujícím příkladu User je model přímo mapující databázovou tabulku bez dědění z ObservableObject:
public class ObservableUser : ObservableObject
{
private readonly User user;
public ObservableUser(User user) => this.user = user;
public string Name
{
get => user.Name;
set => SetProperty(user.Name, value, user, (u, n) => u.Name = n);
}
}
V tomto případě používáme přetížení SetProperty<TModel, T>(T, T, TModel, Action<TModel, T>, string). Podpis je o něco složitější než předchozí – to je nezbytné k tomu, aby byl kód stále velmi efektivní, i když nemáme přístup k záložnímu poli, jako je v předchozím scénáři. Jednotlivé části tohoto podpisu metody si můžeme podrobně projít, abychom lépe porozuměli funkci jednotlivých částí:
-
TModelje argument typu označující typ modelu, který zabalíme. V tomto případě to bude třídaUser. Všimněte si, že toto explicitní zadání nepotřebujeme – kompilátor jazyka C# to automaticky odvodí tím, jak metoduSetPropertyvyvoláváme. -
Tje typ vlastnosti, kterou chceme nastavit.TModelPodobně jako , to je odvozeno automaticky. -
T oldValueje první parametr a v tomto případě používámeuser.Namek předání aktuální hodnoty této vlastnosti, kterou zabalíme. -
T newValueje nová hodnota nastavená na vlastnost a zde předávámevalue, což je vstupní hodnota v rámci setter vlastnosti. -
TModel modelje cílový model, který zabalíme, v tomto případě předáváme instanci uloženouuserv poli. -
Action<TModel, T> callbackje funkce, která se vyvolá, pokud se nová hodnota vlastnosti liší od aktuální hodnoty a vlastnost musí být nastavena. To provede tato funkce zpětného volání, která přijímá jako vstup cílový model a novou hodnotu vlastnosti, která se má nastavit. V tomto případě pouze přiřazujeme vstupní hodnotu (kterou jsme nazvalin) vlastnostiName(provedenímu.Name = n). Je důležité se zde vyhnout zachycení hodnot z aktuálního oboru a pracovat pouze s hodnotami zadanými jako vstup pro zpětné volání, protože to umožňuje kompilátoru jazyka C# ukládat funkci zpětného volání do mezipaměti a provádět řadu vylepšení výkonu. Právě proto zde nepřistupujeme přímo k poliuserani k parametruvaluev setteru, ale místo toho používáme pouze vstupní parametry lambda výrazu.
Metoda SetProperty<TModel, T>(T, T, TModel, Action<TModel, T>, string) výrazně usnadňuje vytváření těchto obalových vlastností, protože zajišťuje načítání i nastavování cílových vlastností a zároveň nabízí velmi kompaktní rozhraní API.
Poznámka:
Ve srovnání s implementací této metody pomocí výrazů LINQ, konkrétně prostřednictvím parametru typu Expression<Func<T>> místo parametrů stavu a zpětného volání, zlepšení výkonu, které lze dosáhnout tímto způsobem, jsou opravdu významné. Konkrétně je tato verze ~200x rychlejší než ta, která používá výrazy LINQ, a neuvádí vůbec žádné přidělení paměti.
Práce s Task<T> vlastnostmi
Je-li vlastnost Task také nutné vyvolat událost oznámení po dokončení úkolu, aby byly vazby aktualizovány ve správný čas. Např. zobrazení indikátoru načítání nebo jiné informace o stavu operace reprezentované úkolem.
ObservableObject má rozhraní API pro tento scénář:
public class MyModel : ObservableObject
{
private TaskNotifier<int>? requestTask;
public Task<int>? RequestTask
{
get => requestTask;
set => SetPropertyAndNotifyOnCompletion(ref requestTask, value);
}
public void RequestValue()
{
RequestTask = WebService.LoadMyValueAsync();
}
}
SetPropertyAndNotifyOnCompletion<T>(ref TaskNotifier<T>, Task<T>, string) Zde se metoda postará o aktualizaci cílového pole, monitorování nového úkolu, pokud je k dispozici, a vyvolání události oznámení po dokončení úkolu. Tímto způsobem je možné vytvořit vazbu na vlastnost úkolu a upozornit na změny stavu.
TaskNotifier<T> je speciální typ zpřístupněný pomocí ObservableObject, který obaluje cílovou instanci Task<T> a zajišťuje potřebnou logiku upozorňování pro tuto metodu. Typ TaskNotifier lze také použít přímo, pokud máte pouze obecný Task.
Poznámka:
Metoda SetPropertyAndNotifyOnCompletion je určena k nahrazení použití NotifyTaskCompletion<T> typu z Microsoft.Toolkit balíčku. Pokud se tento typ používal, lze jej nahradit pouze vnitřní vlastností Task (nebo Task<TResult>) a poté lze metodu SetPropertyAndNotifyOnCompletion použít k nastavení její hodnoty a vyvolání oznámení o změně. Všechny vlastnosti vystavené typem NotifyTaskCompletion<T> jsou k dispozici přímo na Task instancích.
Příklady
- Podívejte se na ukázkovou aplikaci (pro více architektur uživatelského rozhraní) a podívejte se na sadu nástrojů MVVM v akci.
- Další příklady najdete také v jednotkových testech.