Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
WPF-практика 5 События и команды.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.21 Mб
Скачать

Объекты команд

Объекты команд порождаются классом RoutedCommand, который единственный в WPF реализует (и наследует, конечно) интерфейс ICommand, объявленный следующим образом

public interface ICommand

{

event EventHandler CanExecuteChanged;

bool CanExecute(object parameter);

void Execute(object parameter);

}

Реализующий класс RoutedCommand расширяет сигнатуру объявленных в ICommand методов до второго аргумента target

public bool CanExecute(object parameter, System.Windows.IInputElement target)

public void Execute(object parameter, System.Windows.IInputElement target)

где - аргумент parameter содержит сведения о команде, а аргумент target - сведения о целевом элементе команды.

При возбуждении элемента-источника, к которому прикреплена команда (объект RoutedCommand ), вызывается метод CanExecute(). Этот метод возбуждает туннельное событие PreviewCanExecute, которое начинает спускаться от корня визуального дерева элементов к источнику команды и собирает информацию с целевых элементов о возможности выполнения команды. Получив результаты опроса от события PreviewCanExecute метод CanExecute() возбуждает парное восходящее событие CanExecute с заданием оповестить целевые элементы принять состояние в зависимости от полученной информации от события PreviewCanExecute, а сам возвращает флаг возможности или невозможности выполнения команды.

Если метод CanExecute() вернул значение true, значит исполнение команды возможно и следом вызывается метод Execute(), который последовательно возбуждает парные события PreviewExecuted и Executed как указание выполнить команду во всех целевых элементах прикрепленными к ним обработчиками. Событие отмены выполнения CanExecuteChanged вызывается, если диспетчер команд, в котором централизованно выполняются командные операции, обнаруживает в источнике команды изменения, которые могут сделать недействительной команду, вызванную, но еще не выполненную в целевом элементе.

Библиотечные классы команд

Библиотека .NET Framework имеет множество готовых команд, наиболее часто встречающихся в приложениях. Команды представлены в пространствах имен System.Windows. Input и System.Windows. Documents следующими статическими классами:

  • ApplicationCommands

  • ComponentCommands

  • MediaCommands

  • NavigationCommands

  • EditingCommands

В каждом из приведенных классов команда объявлена как статическое свойство только для чтения типа RoutedUICommand (или RoutedCommand ), следовательно при использовании команды создавать экземпляр класса команды не нужно. Команды имеют имена, ассоциируемые с выполняемой задачей, например, Cut, Copy, New и т.д.

Присоединение команды к источнику

Чтобы команда работала, ее нужно присоединить к свойству Command источника команды. Источников, к которым присоединена одна и та же команда, может быть несколько. Элементы, к которым можно присоединить команду, должны наследовать интерфейс ICommandSource. Только такие элементы будут иметь свойство Command. Этих элементов в WPF немного и все они показаны на рисунке

Интерфейс ICommandSource реализует свои свойства в ближайших наследниках ButtonBase, Hyperlink, InputBinding, MenuItem по общему синтаксису:

public System.Windows.Input.ICommand Command { get; set; }

public object CommandParameter { get; set; }

public System.Windows.IInputElement CommandTarget { get; set; }

В источнике для присоединения команды достаточно присвоить значение только ссылке Command на объект команды (на экземпляр RoutedCommand или RoutedUICommand ). Остальные свойства являются необязательными и служат для уточнения команды:

  • CommandParameter - тип данных, определяемый пользователем, который используется для передачи информации обработчикам, реализующим команду

  • CommandTarget - идентифицирует элемент, в котором должна выполняться данная команда. Если значение свойства CommandTarget не задано, в качестве цели команды используется элемент, в котором установлен фокус ввода

Обратите внимание, что два наследуемые источниками команд свойства-ссылки Command и CommandTarget имеют типы интерфейсов, что позволяет адресовать любые команды и целевые элементы, наследующие эти интерфейсы.

Вот, например, как можно присоединить команду Paste к элементу меню в разметке

<StackPanel>

<Menu Header="Edit">

<MenuItem Command="ApplicationCommands.Paste" />

</Menu>

<TextBox />

</StackPanel>

Для библиотечных команд синтаксис разметки допускает использование сокращенной записи, например

<StackPanel>

<Menu Header="Edit">

<MenuItem Command="Paste" />

</Menu>

<TextBox />

</StackPanel>

Теперь, если объект TextBox имеет фокус ввода и буфер обмена содержит текст, то при выборе пользователем этого пункта меню текст из буфера будет вставлен в элемент TextBox. Обратите внимание, что объект MenuItem не устанавливает свойство Header для отображения в нем названия команды Paste. Если свойство для текста названия команды в источнике опущено, то источник способен сам извлекать эту информацию из объекта присоединенной команды.

А вот альтернативный вариант присоединения команды Paste к элементу меню в процедурном коде

// Создание объектов пользовательского интерфейса

StackPanel mainStackPanel = new StackPanel();

TextBox pasteTextBox = new TextBox();

Menu stackPanelMenu = new Menu();

MenuItem pasteMenuItem = new MenuItem();

// Добавление объектов в коллекции панели и меню

stackPanelMenu.Items.Add(pasteMenuItem);

mainStackPanel.Children.Add(stackPanelMenu);

mainStackPanel.Children.Add(pasteTextBox);

// Присоединение библиотечной команды Paste к источнику команд

pasteMenuItem.Command = ApplicationCommands.Paste;

Аналогичный пример можно привести для присоединения команды к контекстному меню.

<StackPanel>

<StackPanel.ContextMenu>

<ContextMenu>

<MenuItem Command="ApplicationCommands.Paste" />

</ContextMenu>

</StackPanel.ContextMenu>

</StackPanel>

// Создание объектов пользовательского интерфейса

StackPanel cmdSourcePanel = new StackPanel();

ContextMenu cmdSourceContextMenu = new ContextMenu();

MenuItem cmdSourceMenuItem = new MenuItem();

// Добавление ContextMenu в StackPanel

cmdSourcePanel.ContextMenu = cmdSourceContextMenu;

cmdSourcePanel.ContextMenu.Items.Add(cmdSourceMenuItem);

// Присоединение библиотечной команды Paste к источнику команд

cmdSourceMenuItem.Command = ApplicationCommands.Paste;