Команда может принимать параметры, через которые в команду можно передать некоторые данные извне. В частности, если мы посмотрим на определение метода Execute
,
то увидим, что он принимает параметр args, через который в команду передаются данные любого типа:
void Execute(object? arg);
Для передачи данных в команду элементы графического интерфейса, которые поддерживают команды, как правило, имеют свойство CommandParameter. Это свойство и представляет передаваемые в команду данные.
Рассмотрим применение параметров команды. Пусть данные представлены следующим классом Person:
public class Person { public string Name { get; set; } public int Age { get; set; } public Person(string name, int age) { Name = name; Age = age; } }
Определим следующий класс модели представления MainViewModel:
using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows.Input; namespace HelloApp; public class MainViewModel : INotifyPropertyChanged { string name = ""; int age; public event PropertyChangedEventHandler? PropertyChanged; public ICommand AddCommand { get; set; } public ICommand RemoveCommand { get; set; } public ObservableCollectionPeople { get; } = new(); public MainViewModel() { // устанавливаем команду добавления AddCommand = new Command(() => { People.Add(new Person(Name, Age)); Name = ""; Age = 0; }); // устанавливаем команду удаления RemoveCommand = new Command((object? args) => { if(args is Person person) People.Remove(person); }); } public string Name { get => name; set { if (name != value) { name = value; OnPropertyChanged(); } } } public int Age { get => age; set { if (age != value) { age = value; OnPropertyChanged(); } } } public void OnPropertyChanged([CallerMemberName] string prop = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop)); } }
Модель представления определяет свойство People, которое представляет коллекцию объектов, а также свойства Name и Age, через которые пользователь будет добавлять в список People новые данные.
MainViewModel определяет две команды. Команда AddCommand по свойствам Name и Age создает объект Person и добавляет его в коллекцию Person.
Команда RemoveCommand
получает параметр:
RemoveCommand = new Command((object? args) => { if(args is Person person) People.Remove(person); });
Для получения параметра в конструктор класса Command передается делегат с одним параметров типа object?
. Такой параметр может представлять любой тип. И в данном случае мы
ожидаем, что будет передаваться удаляемый объект Person. Поэтому преобразуем параметр args к типу Person и удаляем из коллекции People.
В файле MainPage.xaml.cs установим данную модель представления в качестве констекста привязки:
namespace HelloApp; public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); BindingContext = new MainViewModel(); } }
В файле MainPage.xaml установим привязки свойств и команд модели представления к визуальным элементам:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="HelloApp.MainPage"> <VerticalStackLayout Padding="5"> <VerticalStackLayout> <Entry Placeholder="Enter name" Text="{Binding Name}" /> <Entry Placeholder="Enter age" Text="{Binding Age}" /> <Button Text="Save" WidthRequest="100" HorizontalOptions="Start" Command="{Binding AddCommand}" /> </VerticalStackLayout> <ListView x:Name="peopleListView" ItemsSource="{Binding People}"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <VerticalStackLayout> <Label Text="{Binding Name}" /> <Label Text="{Binding Age}" FontSize="14" /> </VerticalStackLayout> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> <Button Text="Remove" WidthRequest="100" HorizontalOptions="Start" Command="{Binding RemoveCommand}" CommandParameter="{Binding Source={x:Reference Name=peopleListView}, Path=SelectedItem}" /> </VerticalStackLayout> </ContentPage>
Вначале страницы определено два текстовых поля, которые привязаны к свойствам Name и Age. А по нажатию кнопки Add срабатывает команда AddCommand
,
которая добавляет введенные в текстовые поля данные в виде объекта Person в список People.
Чуть ниже определен элемент ListView, который выводит список People. И под ListView расположена кнопка удаления, которая привязана к команде RemoveCommand
и
которая в качестве параметра команды передает выделенный объект в ListView:
<Button Text="Remove" WidthRequest="100" HorizontalOptions="Start" Command="{Binding RemoveCommand}" CommandParameter="{Binding Source={x:Reference Name=peopleListView}, Path=SelectedItem}" />
Свойство CommandParameter
также определяется через привязку. Поскольку глобальным констекстом привязки (в том числе контекстом привязки для кнопки удаления)
является модель представления MainViewModel, то в данном случае переопределяем источник привязки на ListView: Source={x:Reference Name=peopleListView}
и
привязываемся к его свойству SelectedItem
.
Таким образом, после выделения объекта в ListView и нажатия на кнопку выделенный объект будет удален:
В примере выше для создания команды использвался необобщенный класс command. Однако можно также использовать его обобщенную версию и типизировать объект Command типом параметра (в данном случае типом Person):
RemoveCommand = new Command<Person>((Person person) => { People.Remove(person); });
В данном случае команда типизированна типом Person, поэтому параметр команды также представляет тип Person. Соответственно мы можем избежать преобразования данных в тип Person.
В примере выше в качестве параметра передавался выделенный объект с помощью выражения привязки. Однако в реальности необязательно использовать привязку. Можно передавать любое значение. Например, передача простого числа
<Button Text="6" Command="{Binding SomeCommand}" CommandParameter="6" />
В данном случае некоторая команда SomeCommand в качестве параметра получит число 6.