Padding="4, 2" Command="{Binding Path=ChangeColorCmd,

    RelativeSource={RelativeSource Mode=FindAncestor,

                    AncestorType={x:Type Window}}}"

    CommandParameter="{Binding ElementName=cboCars, Path=SelectedItem}"/>

<p id="AutBody_Root1292"><strong>Тестирование приложения</strong></p>

Запустите приложение. Кнопка Change Color не будет доступной (рис. 28.8), т.к. автомобиль еще не выбран.

Теперь выберите автомобиль; кнопка Change Color становится доступной, а щелчок на ней обеспечивает изменение цвета, как и ожидалось!

<p id="AutBody_Root1293"><strong>Создание класса CommandBase</strong></p>

Если распространить такой шаблон на AddCarCommand.cs, то итогом стал бы код, повторяющийся среди классов. Это хороший знак о том, что необходим базовый класс. Создайте внутри папки Cmds новый файл класса по имени CommandBase.cs и добавьте оператор using для пространства имен System.Windows.Input. Сделайте класс CommandBase открытым и реализующим интерфейс ICommand. Превратите класс и методы Execute и CanExecute в абстрактные. Наконец, добавьте обновление в событие CanExecuteChanged из класса ChangeColorCommand. Ниже показана полная реализация:

using System;

using System.Windows.Input;

namespace WpfCommands.Cmds

{

  public abstract class CommandBase : ICommand

  {

    public abstract bool CanExecute(object parameter);

    public abstract void Execute(object parameter);

    public event EventHandler CanExecuteChanged

    {

      add => CommandManager.RequerySuggested += value;

      remove => CommandManager.RequerySuggested -= value;

    }

  }

}

<p id="AutBody_Root1294"><strong>Добавление класса AddCarCommand</strong></p>

Добавьте в папку 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 cars)

    {

      return;

    }

    var maxCount = cars.Max(x => x.Id);

    cars.Add(new Car

    {

      Id = ++maxCount,

      Color = "Yellow",

      Make = "VW",

      PetName = "Birdie"

    });

  }

}

<p id="AutBody_Root1295"><strong>Изменение файла MainWindow.xaml.cs</strong></p>

Добавьте открытое свойство типа ICommand по имени AddCarCmd с поддерживающим полем. В теле выражения для свойства возвратите значение поддерживающего поля (создавая экземпляр AddCarCommand, если поддерживающее поле равно null):

private ICommand _addCarCommand = null;

public ICommand AddCarCmd

  => _addCarCommand ??= new AddCarCommand);

<p id="AutBody_Root1296"><strong>Изменение файла MainWindow.xaml</strong></p>

Модифицируйте разметку 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}"/>

Перейти на страницу:

Похожие книги