Добавьте в папку Cmds
новый файл класса по имени AddCarCommand.cs
. Сделайте класс открытым и укажите CommandBase
в качестве базового класса. Поместите в начало файла следующие операторы using
:
using System.Collections.ObjectModel;
using System.Linq;
using WpfCommands.Models;
Ожидается, что параметр должен иметь тип ObservableCollection
, поэтому предусмотрите в методе CanExecute()
соответствующую проверку. Если параметр относится к типу ObservableCollection
, тогда метод Execute()
должен добавить дополнительный объект Car
подобно обработчику события Click
.
public class AddCarCommand :CommandBase
{
public override bool CanExecute(object parameter)
=> parameter is ObservableCollection
public override void Execute(object parameter)
{
if (parameter is not ObservableCollection
{
return;
}
var maxCount = cars.Max(x => x.Id);
cars.Add(new Car
{
Id = ++maxCount,
Color = "Yellow",
Make = "VW",
PetName = "Birdie"
});
}
}
Изменение файла MainWindow.xaml.cs
Добавьте открытое свойство типа ICommand
по имени AddCarCmd
с поддерживающим полем. В теле выражения для свойства возвратите значение поддерживающего поля (создавая экземпляр AddCarCommand
, если поддерживающее поле равно null
):
private ICommand _addCarCommand = null;
public ICommand AddCarCmd
=> _addCarCommand ??= new AddCarCommand());
Изменение файла MainWindow.xaml
Модифицируйте разметку XAML, удалив атрибут Click
и добавив атрибуты Command
и CommandParameter
. Объект AddCarCommand
будет получать список автомобилей из поля со списком cboCars
. Ниже показана полная разметка XAML для кнопки:
Command="{Binding Path=AddCarCmd,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}}}"
CommandParameter="{Binding ElementName=cboCars, Path=ItemsSource}"/>
В результате появляется возможность добавления автомобилей и обновления их цветов (пока с весьма ограниченной функциональностью) с помощью многократно используемого кода, содержащегося в автономных классах.
Изменение класса ChangeColorCommand
Финальным шагом будет обновление класса ChangeColorCommand
, чтобы он стал унаследованным от CommandBase
. Замените интерфейс ICommand
классом CommandBase
, добавьте к обоим методам ключевое слово override
и удалите код события CanExecuteChanged
. Все оказалось действительно настолько просто! Вот как выглядит новый код:
public class ChangeColorCommand : CommandBase
{
public override bool CanExecute(object parameter)
=> parameter is Car;
public override void Execute(object parameter)
{
((Car)parameter).Color = "Pink";
}
}
Объекты RelayCommand
Еще одной реализацией паттерна "Команда" (Command) в WPF является RelayCommand
. Вместо создания нового класса, представляющего каждую команду, данный паттерн применяет делегаты для реализации интерфейса ICommand
. Реализация легковесна в том, что каждая команда не имеет собственного класса. Объекты RelayCommand
обычно используются, когда нет необходимости в многократном применении реализации команды.
Создание базового класса RelayCommand
Как правило, объекты RelayCommand
реализуются в двух классах. Базовый класс RelayCommand
используется при отсутствии каких-либо параметров для методов CanExecute()
и Execute()
, а класс RelayCommand
применяется, когда требуется параметр. Начните с базового класса RelayCommand
, который задействует класс CommandBase
. Добавьте в папку Cmds
новый файл класса по имени RelayCommand.cs
. Сделайте его открытым и укажите CommandBase
в качестве базового класса. Добавьте две переменные уровня класса для хранения делегатов Execute()
и CanExecute()
:
private readonly Action _execute;