Литмир - Электронная Библиотека
A
A

В результате появляется возможность добавления автомобилей и обновления их цветов (пока с весьма ограниченной функциональностью) с помощью многократно используемого кода, содержащегося в автономных классах.

Изменение класса 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<T>
применяется, когда требуется параметр. Начните с базового класса
RelayCommand
, который задействует класс
CommandBase
. Добавьте в папку
Cmds
новый файл класса по имени
RelayCommand.cs
. Сделайте его открытым и укажите
CommandBase
в качестве базового класса. Добавьте две переменные уровня класса для хранения делегатов
Execute()
и
CanExecute()
:

private readonly Action _execute;

private readonly Func<bool> _canExecute;

Создайте три конструктора. Первый — стандартный конструктор (необходимый для производного класса

RelayCommand<T>
), второй — конструктор, который принимает параметр
Action
, и третий — конструктор, принимающий параметры
Action
и
Func
:

public RelayCommand(){}

public RelayCommand(Action execute) : this(execute, null) { }

public RelayCommand(Action execute, Func<bool> canExecute)

{

  _execute = execute

    ?? throw new ArgumentNullException(nameof(execute));

  _canExecute = canExecute;

}

Наконец, реализуйте переопределенные версии

CanExecute()
и
Execute()
. Метод
CanExecute()
возвращает
true
, если параметр
Func
равен
null
; если же параметр
Func
не
null
, то он выполняется и возвращается
true
. Метод
Execute()
выполняет параметр типа
Action
.

public override bool CanExecute(object parameter)

  => _canExecute == null || _canExecute();

public override void Execute(object parameter) { _execute(); }

Создание класса RelayCommand<T>

Добавьте в папку

Cmds
новый файл класса по имени
RelayCommandT.cs
. Класс
RelayCommandT
является почти полной копией базового класса, исключая тот факт, что все делегаты принимают параметр. Сделайте класс открытым и обобщенным, а также унаследованным от базового класса
RelayCommand
:

public class RelayCommand&lt;T&gt; : RelayCommand

Добавьте две переменные уровня класса для хранения делегатов

Execute()
и
CanExecute()
:

private readonly Action&lt;T&gt; _execute;

private readonly Func&lt;T, bool&gt; _canExecute;

Создайте два конструктора. Первый из них принимает параметр

Action&lt;T&gt;
, а второй — параметры
Action&lt;T&gt;
и
Func&lt;T,bool&gt;
:

public RelayCommand(Action&lt;T&gt; execute):this(execute, null) {}

public RelayCommand(

  Action&lt;T&gt; execute, Func&lt;T, bool&gt; canExecute)

  {

  _execute = execute

    ?? throw new ArgumentNullException(nameof(execute));

  _canExecute = canExecute;

}

572
{"b":"847442","o":1}