Старая добрая парадигма программирования для взаимодействия приложения и пользователя состоит в генерации событий и их обработки. События сигнализируют о возникновении определенных обстоятельств, требующих реакции приложения: будь то действия пользователя, возникновение критических ситуаций или определенных условий. События возбуждаются источниками и перехватываются обработчиками (если они есть), которые и выполняют закрепленные за ними действия в ответ на эти события.
События являются удобным инструментом программирования, делающим код более прозрачным и естественным. События - это низкий уровень модели программирования. Их применение в программировании пользовательского интерфейса, когда управление приложением на уровне задач может осуществляться через несколько разных инструментов, требующих одинаковой реакции, иногда становится громоздким. Может потребоваться не только создание нескольких обработчиков с дублирующим кодом, но и необходимость следить за состоянием сразу нескольких интерфейсных элементов, инициирующих задачу, когда действие выполнить невозможно.
Прямую реакцию приложения на определенные действия пользователя обычно называют задачами, а сами запросы на действия - командами. В WPF разработан новый механизм, существенно упрощающий связывание задач, запросов и действий, который называется командами. Команды, как и события, в WPF являются маршрутизованными (Routed - направленный). Но здесь есть отличие: события могут туннелировать и всплывать, а команды только всплывают (команды бывают только пузырьковые, восходящие, всплывающие).
На самом деле всплывают не сами команды, а генерируемые ими маршрутизованные события. Существует всего несколько специальных событий для поддержки команд. В классе CommandBinding определены события PreviewCanExecute и CanExecute типа CanExecuteRoutedEventHandler, а также события PreviewExecuted и Executed типа ExecutedRoutedEventHandler. В интерфейсе ICommand, наследуемом классом RoutedCommand, определено еще событие CanExecuteChanged. Эти события проходят по дереву элементов до тех пор, пока не будет найден прослушивающий элемент с привязкой CommandBinding для конкретной команды. Вот и все события команд.
Команда включает в себя несколько ингредиентов:
- Объект команды - представляет определенную задачу и следит за тем, когда она может быть выполнена. Самого кода, выполняющего задачу, команда не содержит.
- Источник команды - элемент управления, жест (комбинация клавиш, клавиш и мыши, функциональные клавиши) или специализированный код, при активизации которого запускается команда. Источников одной команды может быть несколько: меню, контекстное меню, кнопка панели инструментов, жесты пользователя
- Обработчик команды - метод, который выполняется при запуске команды
- Прослушивающий элемент привязки обработчиков - объект, занимающийся отслеживанием маршрутизованных событий команды и переадресующий ее выполнение соответствующему обработчику
- Целевой объект команды - необязательный элемент, который ждет обслуживания своей командой и на котором команда выполняется (например, выделенный текст, который нужно вырезать или скопировать в буфер обмена). Целевым объектом может служить элемент привязки обработчиков команды при прямом вызове, в котором WPF начинает искать привязку.