Классы Windows Presentation Foundation System.Object DispatcherObject Application DependencyObject NavigationService FrameworkTemplate Visual ContentElement UIElement FrameworkContentElement Style FrameworkElement Page Shape TextBlock ContentControl RangeBase TextBoxBase Frame Slider TextBox Window ProgressBar RichTextBox Grid ItemsControl Menu ContextMenu HeaderedItemsControl MenuItem Button Toolbar TreeViewItem Selector RepeatButton TabControl ToggleButton CheckBox Canvas MenuBase NavigationWindow ButtonBase Panel ToolBarTray Control RadioButton ListBox ListView TreeView ComboBox Маршрутизируемые команды WPF реализует модель маршрутизируемых команд (routed command), которая поддерживает привязку одной команды к различным элементам управления с более слабой связью, чем обычная обработка событий. Особенности маршрутизируемых команд по сравнению с обычной обработкой событий: • источник команды (элемент управления) и обработчик команды не связаны прямой ссылкой друг на друга, как при обработке событий; • маршрутизируемые команды автоматически включают (отключают) связанные с ними элементы управления при включении (отключении) команды; • можно определить сочетания клавиш мыши и клавиатуры как дополнительный способ вызова команды. #Компоненты команды Модель маршрутизируемой команды WPF включает следующие основные компоненты: • команда (command) – действие, которое должно быть выполнено; • источник команды (command source ) – объект, вызывающий команду; • целевые объекты команд (command target ) – объекты, на которых должна быть выполнена команда; • привязка (command binding) команд. Команда представляет собой экземпляр класса RoutedCommand и не реализует логику команды. Логика команды реализуется в обработчиках событий Executed и CanExecute, которые возбуждаются для целевого объекта и присоединяется к команде с помощью объекта CommandBinding. Чтобы связать команду с элементом управления, можно: • добавить объект CommandBinding к коллекции команд элемента управления; • присвоить значение свойству Command элемента управления, если его класс реализуют интерфейс ICommandSource. Классы для работы с командами Object RoutedCommand RoutedUICommand CommandBinding CommandManager EventArgs RoutedEventArgs ExecutedRoutedEventArgs CanExecuteRoutedEventArgs Классы RoutedCommand и RoutedUICommand определяют команду, маршрутизируемую по дереву элементов. Класс CommandBinding поддерживает привязку команды к обработчикам событий, реализующим данную команду. Класс CommandManager управляет моделью маршрутизируемых команд WPF содержит методы для регистрации объектов CommandBinding, добавления и удаления обработчиков событий и сервисы для запроса состояния команды. Классы ExecutedRoutedEventArgs и CanExecuteRoutedEventArgs предоставляют данные для маршрутизируемых событий Executed и PreviewExecuted. Классы RoutedCommand и RoutedUICommand Классы определяют команду, маршрутизируемую по дереву элементов. Класс RoutedUICommand отличается от своего базового класса RoutedCommand только наличием свойства Text. Методы Execute и CanExecute класса RoutedCommand не содержат логику приложения для команды. Методы только инициируют события: • метод Execute инициирует события PreviewExecuted и Executed; • метод CanExecute инициирует события PreviewCanExecute и CanExecute. public RoutedCommand (); public RoutedCommand ( string name, Type ownerType ); public RoutedCommand ( string name, Type ownerType, InputGestureCollection inputGestures ); System.Object RoutedCommand: ICommand RoutedUICommand public bool CanExecute ( Object parameter, IInputElement target ); public void Execute ( Object parameter, IInputElement target ); public InputGestureCollection InputGestures { get; } public string Name { get; } public Type OwnerType { get; } public event EventHandler CanExecuteChanged; public RoutedUICommand (); public RoutedUICommand ( string text, string name, Type ownerType ); public RoutedUICommand ( string text, string name, Type ownerType, InputGestureCollection inputGestures ) ; public string Text { get; set; } Логика команды находится в обработчиках событий, присоединенных к команде с помощью объектов CommandBinding. Интерфейс ICommand public interface ICommand { bool CanExecute( Object parameter ); void Execute( Object parameter ); event EventHandler CanExecuteChanged; } Интерфейс IСommand реализуется классом RoutedCommand и наследуется классом RoutedUICommand. Это единственные классы WPF, реализующие интерфейс ICommand. Метод CanExecute возвращает значение true, если команду можно выполнить для целевого объекта (command target). В методе Execute выполняются действия, ассоциированные с командой. Через параметры методов CanExecute и Execute можно передать ссылку на данные (допускается значение null). Событие CanExecuteChanged происходит, когда менеджер команд диагностирует изменение в источнике команды, которое может привести к невозможности выполнения уже инициированной(raised), но еще не выполненной команды. Обычно в ответ на это событие источник команды вызывает метод CanExecute. Класс CommandBinding Класс реализует привязку команды RoutedCommand к обработчикам, в которых реализована логика команды. В классе CommandBinding определены четыре события public public public public event event event event CanExecuteRoutedEventHandler CanExecute; ExecutedRoutedEventHandler Executed; CanExecuteRoutedEventHandler PreviewCanExecute; ExecutedRoutedEventHandler PreviewExecuted; Конструкторы класса связывают команду с обработчиками событий PreviewExecuted, Executed, PreviewCanExecute,CanExecute public CommandBinding( ICommand command, ExecutedRoutedEventHandler executed ); public CommandBinding( ICommand command, ExecutedRoutedEventHandler executed, CanExecuteRoutedEventHandler canExecute ); Коллекция CommandBindings в классе UIElement Класс UIElement поддерживает коллекцию объектов CommandBinding: public CommandBindingCollection CommandBindings { get; } Коллекция CommandBindingCollection реализует интерфейс IList и содержит методы для работы с коллекцией, в частности, public int Add( CommandBinding commandBinding ); public void Remove( CommandBinding commandBinding ); В примере два объекта CommandBinding добавляются к коллекции команд главного окна приложения в XAML . <Window.CommandBindings> <CommandBinding Command="ApplicationCommands.Open" Executed="OpenCommandHandler" CanExecute="CanOpenExecuteHandler"/> <CommandBinding Command="ApplicationCommands.Copy" Executed="CopyCommandHandler" /> </Window.CommandBindings> Свойство Command. Интерфейс ICommandSource В классах, реализующих интерфейс ICommandSource, команду и элемент управления можно связать с помощью свойства Command. Интерфейс ICommandSource реализуют наследники классов ButtonBase, MenuItem, ListBoxItem и HyperLink. public interface ICommandSource { ICommand Command { get; } Object CommandParameter { get; } IInputElement CommandTarget { get; } } Свойство CommandParameter возвращает ссылку на определенный пользователем объект с данными, который можно передать команде при ее выполнении. Свойство CommandTarget возвращает ссылку на объект, для которого выполняется команда. При использовании с RoutedCommand для целевого объекта возбуждаются события Executed и CanExecute. Если не установлено значение свойства CommandTarget как целевой трактуется элемент управления, имеющий фокус ввода с клавиатуры. В примере свойству Command кнопки присваивается ссылка на команду Open из статического класса ApplicationCommands. <Button Command="ApplicationCommands.Open“> <Image Source="{StaticResource Image_Open}" /> </Button> ExecutedRoutedEventArgs и CanExecuteRoutedEventArgs Классы предоставляют данные для маршрутизируемых событий Executed и PreviewExecuted. System.Object public RoutedEvent RoutedEvent { get; set; } System.EventArgs public Object Source { get; set; } public bool Handled { get; set; } System.Windows.RoutedEventArgs public Object OriginalSource { get; } System.Windows.Input. System.Windows.Input. ExecutedRoutedEventArgs CanExecuteRoutedEventArgs public ICommand Command { get; } public bool CanExecute { get; set; } public Object Parameter { get; } public ICommand Command { get; } public bool ContinueRouting { get; set; } public Object Parameter { get; } Класс СommandManager Класс CommandManager управляет моделью команд WPF и содержит • методы для регистрации объектов CommandBinding и InputBinding; • методы для добавления и удаления обработчиков событий; • сервисы для запроса состояния команды. Класс содержит метод для регистрации команды для класса (а не для экземпляра класса): public static void RegisterClassCommandBinding( Type type, CommandBinding commandBinding ); Класс содержит методы, которые можно использовать для добавления к элементу управления обработчиков, связанных с командой: public static void AddExecutedHandler ( UIElement element, ExecutedRoutedEventHandler handler); public static void RemoveExecutedHandler ( UIElement element, ExecutedRoutedEventHandler handler ); public static void AddPreviewExecutedHandler ( UIElement element, ExecutedRoutedEventHandler handler ); public static void RemovePreviewExecutedHandler ( UIElement element, ExecutedRoutedEventHandler handler ); Команды из статических классов WPF Библиотека WPF содержит более 100 предопределенных команд, которые находятся в 5 статических класcах: • ApplicationCommands • NavigationCommands (BrowseForward, BrowseBack, Zoom , Search,…) • MediaCommands (Play, Pause, Record, Stop,…) • EditingCommands (AlignCenter, DeleteNextWord, MoveToLineEnd,…) • ComponentCommands ( MoveDown, MoveFocusUp, SelectToEnd,…) Все предопределенные команды доступны как статические свойства классов и имеют сигнатуру public static RoutedUICommand CommandName { get; } Cтатический класc ApplicationCommands содержит статические свойства (команды): CancelPrint Delete Paste Save Close Find Print SaveAs ContextMenu Help PrintPreview SelectAll Copy New Properties Stop CorrectionList NotACommand Redo Undo Cut Open Replace Привязки ввода Object DispatcherObject DependencyObject InputGesture KeyGesture MouseGesture InputBinding KeyBinding MouseBinding Привязка ввода определяет пару команда-жест (gesture) устройства ввода, который инициирует выполнение команды. Привязки описываются классами, производными от абстрактного класса InputBinding. Жесты ввода – объекты классов KeyGesture и MouseGesture. Класс UIElement поддерживает коллекцию привязок ввода, которая доступна через свойство InputBindings: public InputBindingCollection InputBindings { get; } Класс KeyGesture Определяет сочетание клавиш, которое можно использовать для вызова команды. Конструкторы и свойства класса KeyGesture(Key) ; KeyGesture(Key, ModifierKeys); KeyGesture(Key, ModifierKeys, String); Key{get; set;} Modifiers{get; set;} DisplayString{get; set;} Перечисление ModifierKeys задает набор клавиш CTRL, SHIFT и ALT. Имеет значения None, Alt, Control, Shift и Windows. Перечисление Key задает клавиши клавиатуры. Допустимый объект KeyGesture должен содержать в точности одно значение перечисления Key и одно или несколько значений перечисления ModifierKeys. Исключением являются функциональные клавиши и клавиши цифровой дополнительной клавиатуры. Можно создать KeyGesture, только из клавиши F2, но нельзя создать жест только из клавиши A. Класс MouseGesture Определяет жест ввода мыши, который может использоваться для вызова команды. Конструкторы и свойства класса MouseGesture() ; MouseGesture(MouseAction); MouseGesture(MouseAction, ModifierKeys); MouseAction{get; set;} Modifiers{get; set;} Перечисление ModifierKeys задает набор клавиш CTRL, SHIFT и ALT. Имеет значения None, Alt, Control, Shift и Windows. Перечисление MouseAction имеет значения None, LeftClick, RightClick, MiddleClick, WheelClick, LeftDoubleClick, RightDoubleClick и MiddleDoubleClick. Допустимый объект KeyGesture может не содержать значений перечисления ModifierKeys. Класс KeyBinding Объект KeyBinding связывает жест KeyGesture с командой. Класс KeyBinding содержит свойства Key, Modifiers и Gesture, которые можно использовать для определения клавиш быстрого доступа к команде. Свойство Gesture и пара свойств Key и Modifiers представляют один и тот же объект, поэтому в XAML при определении KeyBinding жест можно задать двумя способами: • определить атрибут Gesture в виде единой строки, например: "CTRL+P“; • определить два атрибута - Key и Modifiers. В XAML рекомендуется использовать атрибут Gesture. Обычно привязки ввода определяются в шаблоне элемента управления путем добавления в коллекцию InputBindings элементов MouseBinding и/или KeyBinding. В примере в коллекцию InputBindings привязок ввода окна добавлены две привязки к команде Open <Window.InputBindings> <KeyBinding Command="ApplicationCommands.Open" Gesture="CTRL+O" /> <KeyBinding Command="ApplicationCommands.Open" Gesture="F8"/> </Window.InputBindings> Класс KeyBinding. Пример привязки в коде В следующем примере в коде создается объект KeyBinding , который связывает команду Open с жестом Alt+O. Привязка добавляется в коллекцию InputBindings главного окна приложения. private void button_add_gestures_Click(object sender, RoutedEventArgs e) { KeyBinding OpenKeyBinding = new KeyBinding( ApplicationCommands.Open, Key.O, ModifierKeys.Alt); this.InputBindings.Add(OpenKeyBinding); } Перечисление ModifierKeys задает набор клавиш CTRL, SHIFT и ALT. Имеет значения None, Alt, Control, Shift и Windows. Перечисление Key задает клавиши клавиатуры. Класс MouseBinding Объект MouseBinding связывает жест MouseGesture с командой. Класс MouseBinding содержит свойства MouseAction и Gesture, которые можно использовать для определения жеста для команды Свойства Gesture и MouseAction представляют один и тот же объект, поэтому в XAML для задания жеста в MouseBinding можно использовать один из атрибутов - Gesture или MouseAction. Перечисление MouseAction имеет значения None, LeftClick, RightClick, MiddleClick, WheelClick, LeftDoubleClick, RightDoubleClick и MiddleDoubleClick. В XAML атрибут Gesture элемента MouseBinding можно задать в виде одной строки, например: "CTRL+LeftClick". В примере в коллекцию InputBindings привязок ввода окна добавлены привязки к команде Open <Window.InputBindings> <KeyBinding Command="ApplicationCommands.Open" Gesture="CTRL+O" /> <KeyBinding Command="ApplicationCommands.Open" Gesture="F8"/> <MouseBinding Gesture=“Ctrl+WheelClick" Command="ApplicationCommands.Open" /> </Window.InputBindings>