Язык программирования C#9 и платформа .NET5
Шрифт:
Изменение класса 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
Еще
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<T> : RelayCommand
Добавьте две переменные уровня класса для хранения делегатов
Execute
и CanExecute
:
private readonly Action<T> _execute;
private readonly Func<T, bool> _canExecute;
Создайте два конструктора. Первый из них принимает параметр
Action<T>
, а второй — параметры Action<T>
и Func<T,bool>
:
public RelayCommand(Action<T> execute):this(execute, null) {}
public RelayCommand(
Action<T> execute, Func<T, bool> canExecute)
{
_execute = execute
?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
Наконец, реализуйте переопределенные версии
CanExecute
и Execute
. Метод CanExecute
возвращает true
, если Func
равно null
, а иначе выполняет Func
и возвращает true
. Метод Execute
выполняет параметр типа Action
.
public override bool CanExecute(object parameter)
=> _canExecute == null || _canExecute((T)parameter);
public override void Execute(object parameter)
{ _execute((T)parameter); }
Изменение файла MainWindow.xaml.cs
Когда используются объекты
RelayCommand
, при конструировании новой команды должны указываться все методы для делегатов. Это вовсе не означает, что код нуждается в помещении внутрь файла отделенного кода (как показано здесь); он просто должен быть доступным из файла отделенного кода. Код может находиться в другом классе (или даже в другой сборке), что дает преимущества инкапсуляции, связанные с созданием специального класса команды. Добавьте новую закрытую переменную типа
RelayCommand<Car>
и открытое свойство по имени DeleteCarCmd
;
private RelayCommand<Car> _deleteCarCommand = null;
public RelayCommand<Car> DeleteCarCmd
=> _deleteCarCommand ??=
new RelayCommand<Car>(DeleteCar,CanDeleteCar));
Также потребуется создать методы
DeleteCar
и CanDeleteCar
:
Поделиться:
Популярные книги
Мимик нового Мира 13
12. Мимик!
Фантастика:
боевая фантастика
юмористическая фантастика
рпг
5.00
рейтинг книги
Идеальный мир для Лекаря 15
15. Лекарь
Фантастика:
боевая фантастика
юмористическая фантастика
аниме
5.00
рейтинг книги
Адепт: Обучение. Каникулы [СИ]
6. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.15
рейтинг книги
Ты всё ещё моя
4. Под запретом
Любовные романы:
современные любовные романы
7.00
рейтинг книги
Враг из прошлого тысячелетия
4. Соприкосновение миров
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 7
7. Меркурий
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Книга пяти колец
1. Книга пяти колец
Фантастика:
фэнтези
6.00
рейтинг книги
Кодекс Охотника. Книга XIII
13. Кодекс Охотника
Фантастика:
боевая фантастика
попаданцы
аниме
7.50
рейтинг книги
Вперед в прошлое 3
3. Вперёд в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Идущий в тени 4
4. Идущий в тени
Фантастика:
боевая фантастика
6.58
рейтинг книги
Кодекс Охотника. Книга VI
6. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Охотника. Книга XII
12. Кодекс Охотника
Фантастика:
боевая фантастика
городское фэнтези
аниме
7.50
рейтинг книги
Мимик нового Мира 7
6. Мимик!
Фантастика:
юмористическое фэнтези
постапокалипсис
рпг
5.00
рейтинг книги
Сыночек в награду. Подари мне любовь
1. Суровые отцы
Любовные романы:
современные любовные романы
5.00