Použití příkazů v modelu viewmodel
Viděli jste, jak získat data z modelů viewmodelů do uživatelského rozhraní a jak můžete pomocí obousměrné vazby získat data zpět do svých modelů viewmodelů.
Použití obousměrných vazeb, jako je to preferovaný způsob reakce na změny z uživatelského rozhraní při každé změně dat . Mnoho věcí, které bychom zpracovávali jako události , je možné zpracovat pomocí obousměrných vazeb a MVVM. Další příklady jsou například Switch.IsToggled
a Slider.Value
které se dají v našem modelu viewmodel promítnout jako logická nebo celočíselná hodnota, aniž byste museli používat události.
Existují ale některé věci, například aktivace Button
, MenuItem
které nejsou přímo svázané se změnou dat. Tyto interakce stále vyžadují zpracování podobné událostem. Vzhledem k tomu, že tyto komponenty uživatelského rozhraní obvykle vyvolávají určitou logiku s daty, chceme tuto logiku v modelu viewmodel. Ale nechceme je zpracovávat jako Clicked
události Selected
v kódu, pokud je to možné. Chceme, aby bylo co nejvíce v modelu viewmodel, tak je to testovatelné.
Použití vzoru příkazu
Mnoho ovládacích prvků .NET MAUI, které mají tento druh interakce, podporují vazbu na vlastnost, která zveřejňuje ICommand
rozhraní. Tato vlastnost je s největší pravděpodobností pojmenována Command
. Tlačítko je jedním z příkladů:
<Button Text="Give Bonus" Command="{Binding GiveBonusCommand}" />
Ovládací prvek ví, kdy má příkaz vyvolat. Například tlačítko vyvolá příkaz, když se stiskne. Příkaz v tomto příkladu je vázán na GiveBonusCommand
vlastnost viewmodel. Typ vlastnosti musí implementovat ICommand
rozhraní. Kód by vypadal přibližně takto:
public class EmployeeViewModel : INotifyPropertyChanged
{
public ICommand GiveBonusCommand {get; private set;}
...
}
Rozhraní ICommand
má metodu Execute
, která se volá při kliknutí na tlačítko. Tímto způsobem ICommand.Execute
přímo nahradí Button.Click
kód zpracování událostí.
Úplné ICommand
rozhraní má dvě další metody: CanExecute
a CanExecuteChanged
které se používají k určení, zda se má ovládací prvek zobrazit povolený nebo zakázaný.
Například tlačítko se může zobrazit šedě, pokud CanExecute
vrátí hodnotu false.
ICommand
Toto rozhraní vypadá v jazyce C#:
public interface ICommand
{
bool CanExecute(object parameter);
void Execute(object parameter);
event EventHandler CanExecuteChanged;
}
Použití třídy Command
Tento vzor příkazu umožňuje udržovat čisté oddělení chování uživatelského rozhraní od implementace uživatelského rozhraní. Pokud ale potřebujete vytvořit samostatnou třídu pro implementaci každé obslužné rutiny událostí, může to komplikovat váš kód.
Místo vytváření několika vlastních tříd, které implementují rozhraní, je běžné použít Command
nebo Command<T>
. Tyto třídy implementují ICommand
, ale zpřístupňují jeho chování jako vlastnosti v modelu viewmodel, který můžete nastavit. To vám umožní implementovat GiveBonusCommand
vlastnost popsanou dříve zcela v rámci naší třídy viewmodel:
public class EmployeeViewModel : INotifyPropertyChanged
{
public ICommand GiveBonusCommand {get; private set;}
public EmployeeViewModel(Employee model)
{
GiveBonusCommand = new Command(GiveBonusExecute, GiveBonusCanExecute)
}
void GiveBonusExecute()
{
//logic for giving bonus
}
bool GiveBonusCanExecute()
{
//logic for deciding if "give bonus" button should be enabled.
}
}
V tomto kódu Execute
je chování poskytováno metodou GiveBonusExecute
. A CanExecute
je poskytována GiveBonusCanExecute
. Delegáty na tyto metody jsou předány konstruktoru Command
. V tomto příkladu neexistuje žádná implementace pro CanExecuteChanged
.
Zjednodušení pomocí MVVM Toolkit
Knihovna MVVM Toolkit obsahuje implementace ICommand
známé jako RelayCommand
a AsyncRelayCommand
. Poskytuje také generátory zdrojů pro další zjednodušení tohoto kódu. V následujícím příkladu GiveBonusCommand
se vygeneruje nastavení metody pro volání ke spuštění a volání, aby bylo možné zjistit, zda je možné provést. Atribut [RelayCommand]
se používá v GiveBonus
metodě a vygeneruje GiveBonusCommand
. Navíc nastavením CanExecute
vlastnosti atributu na název metody, kterou chceme připojit k CanExecute
metodě ICommand
, vygeneruje kód pro nastavení pro nás.
public partial class EmployeeViewModel : ObservableObject
{
public EmployeeViewModel(Employee model)
{
}
[RelayCommand(CanExecute = nameof(GiveBonusCanExecute))]
void GiveBonus()
{
//logic for giving bonus
}
bool GiveBonusCanExecute()
{
//logic for deciding if "give bonus" button should be enabled.
return true;
}
}
Sada MVVM Toolkit také zpracovává async
metody, které jsou běžné v programování .NET.
Příkazy s parametry
Rozhraní ICommand
přijímá object
parametr pro metody CanExecute
a Execute
metody. Rozhraní .NET MAUI implementuje toto rozhraní bez kontroly typu prostřednictvím Command
třídy. Delegáti, které připojíte k příkazu, musí provést vlastní kontrolu typů, aby se zajistilo, že je předán správný parametr. Rozhraní .NET MAUI také poskytuje implementaci Command<T>
, ve které nastavíte typ očekávaného parametru. Při vytváření příkazu, který přijímá jeden typ parametru, použijte Command<T>
.
Ovládací prvky .NET MAUI, které implementují vzor příkazu, poskytují CommandParameter
vlastnost. Nastavením této vlastnosti můžete předat parametr příkazu při vyvolání pomocí Execute
, nebo při kontrole CanExecute
stavu metody.
V tomto příkladu se řetězcová hodnota 25 odešle do příkazu:
<Button Text="Give Bonus" Command="{Binding GiveBonusCommand}" CommandParameter="25" />
Příkaz by potřeboval interpretovat a převést tento parametr řetězce. Existuje mnoho způsobů, jak poskytnout parametr silného typu.
Místo použití syntaxe atributů k definování
CommandParameter
použijte elementy XAML.<Button Text="Give Bonus" Command="{Binding GiveBonusCommand}"> <Button.CommandParameter> <x:Int32>25</x:Int32> </Button.CommandParameter> </Button>
Vytvořte vazbu na
CommandParameter
instanci správného typu.CommandParameter
Pokud je vázán na nesprávný typ, použijte převaděč pro převod hodnoty na správný typ.