Параметры команды

Последнее обновление: 24.01.2023

Команда может принимать параметры, через которые в команду можно передать некоторые данные извне. В частности, если мы посмотрим на определение метода 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 ObservableCollection People { 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 и нажатия на кнопку выделенный объект будет удален:

Параметры комманд и свойство CommandParameter в реализации паттерна MVVM в приложении на .NET MAUI и C#

Типизация команды

В примере выше для создания команды использвался необобщенный класс 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.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850