Главная страница Случайная страница Разделы сайта АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Создание и привязка команд
Мы объявили псевдонимы команд как общедоступные поля класса Window1. Команды, которые имеют встроенные жесты или не должны иметь жестов, мы инициализировали сразу. Две команды только объявили, но сами объекты собираемся создать в коде. Код создания этих команд мы поместим в статический конструктор для добавления жестов. Это нужно для того, что добавление жестов требует действий, а это разрешено только в методах. Конструктор должен быть обязательно статическим, чтобы мог выполниться до создания экземпляра окна. Все команды должны к этому времени уже существовать, поскольку используются в разметке окна при создании интерфейсных элементов.
Не забывайте, что статический конструктор класса в C# не принимает параметров и может существовать только в единственном экземпляре (если объявим). Теперь в двух пользовательских командах имеются как жесты, так и вся необходимая информация для отображения в пунктах меню. В соответствии с планом, присоединим команды к источникам, вначале в коде.
Когда вы начнете вручную набирать запись xmlns: myCmd=, то после ввода знака присваивания IntelliSense выдаст подсказку, в которой нужно выбрать выделенную на снимке опцию списка
В результате будет догенерирована следующая запись < Window x: Class=" Notepad2.Window1" xmlns=" https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns: x=" https://schemas.microsoft.com/winfx/2006/xaml" xmlns: myCmd=" clr-namespace: Notepad2" Title=" Window1: Управление состоянием источников команд" Width=" 500" Height=" 375" MinWidth=" 500" MinHeight=" 375" WindowStartupLocation=" CenterScreen" ResizeMode=" CanResizeWithGrip" Loaded=" Window_Loaded" Icon=" Notepad.ico" Closing=" Window_Closing" Activated=" Window_Activated" >.............................................. < /Window>Теперь отредактируем разметку 12 запланированных источников задач в соответствии с таблицей
Правленный код разметки станет таким (для удобства файл Window1.xaml с новым содержимым приводится полностью) < Window x: Class=" Notepad2.Window1" xmlns=" https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns: x=" https://schemas.microsoft.com/winfx/2006/xaml" xmlns: myCmd=" clr-namespace: Notepad2" Title=" Window1: Управление состоянием источников команд" Width=" 500" Height=" 375" MinWidth=" 500" MinHeight=" 375" WindowStartupLocation=" CenterScreen" ResizeMode=" CanResizeWithGrip" Loaded=" Window_Loaded" Icon=" Notepad.ico" Closing=" Window_Closing" Activated=" Window_Activated" > < Window.Resources> <! -- File --> < Image x: Shared=" False" x: Key=" iconNew" Source=" Images/NewDocumentHS.png" Width=" 16" Height=" 16" /> < Image x: Shared=" False" x: Key=" iconOpen" Source=" Images/OpenHS.png" Width=" 16" Height=" 16" /> < Image x: Shared=" False" x: Key=" iconSave" Source=" Images/SaveHS.png" Width=" 16" Height=" 16" /> < Image x: Shared=" False" x: Key=" iconPageSetup" Source=" Images/PrintSetupHS.png" Width=" 16" Height=" 16" /> < Image x: Shared=" False" x: Key=" iconPrintPreview" Source=" Images/PrintPreviewHS.png" Width=" 16" Height=" 16" /> < Image x: Shared=" False" x: Key=" iconPrint" Source=" Images/PrintHS.png" Width=" 16" Height=" 16" /> <! -- Edit --> < Image x: Shared=" False" x: Key=" iconUndo" Source=" Images/Edit_UndoHS.png" Width=" 16" Height=" 16" /> < Image x: Shared=" False" x: Key=" iconRedo" Source=" Images/Edit_RedoHS.png" Width=" 16" Height=" 16" /> < Image x: Shared=" False" x: Key=" iconCut" Source=" Images/CutHS.png" Width=" 16" Height=" 16" /> < Image x: Shared=" False" x: Key=" iconCopy" Source=" Images/CopyHS.png" Width=" 16" Height=" 16" /> < Image x: Shared=" False" x: Key=" iconPaste" Source=" Images/PasteHS.png" Width=" 16" Height=" 16" /> < Image x: Shared=" False" x: Key=" iconDelete" Source=" Images/DeleteHS.png" Width=" 16" Height=" 16" /> < Image x: Shared=" False" x: Key=" iconFind" Source=" Images/FindHS.png" Width=" 16" Height=" 16" /> < Image x: Shared=" False" x: Key=" iconFont" Source=" Images/FontHS.png" Width=" 16" Height=" 16" /> < /Window.Resources> < DockPanel LastChildFill=" True" > <! -- Меню --> < Menu DockPanel.Dock=" Top" > < MenuItem Header=" _File" > <! -- Сокращенные варианты подключения иконок с использованием статических ресурсов --> < MenuItem Name=" itemNew" Click=" NewOnExecute" Header=" _New" InputGestureText=" Ctrl+N" Icon=" {StaticResource iconNew}" /> < MenuItem Name=" itemOpen" Click=" OpenOnExecute" Header=" _Open..." InputGestureText=" Ctrl+O" Icon=" {StaticResource iconOpen}" /> < MenuItem Name=" itemSave" Command=" myCmd: Window1.SaveCommand" Header=" _Save" Icon=" {StaticResource iconSave}" /> < MenuItem Name=" itemSaveAs" Click=" SaveAsOnExecute" Header=" Save _As..." /> < Separator /> < MenuItem Name=" itemPageSetup" Command=" myCmd: Window1.PageSetupCommand" Header=" Page Set_up..." Icon=" {StaticResource iconPageSetup}" /> < MenuItem Name=" itemPrintPreview" Click=" PrintPreviewOnExecute" Header=" P_rint Preview" InputGestureText=" Ctrl+F2" Icon=" {StaticResource iconPrintPreview}" /> < MenuItem Name=" itemPrint" Click=" PrintOnExecute" Header=" _Print..." InputGestureText=" Ctrl+P" Icon=" {StaticResource iconPrint}" /> < Separator /> < MenuItem Name=" itemExit" Click=" ExitOnExecute" Header=" E_xit" /> < /MenuItem> < MenuItem Header=" _Edit" > < MenuItem Name=" itemUndo" Command=" myCmd: Window1.UndoCommand" Header=" _Undo" Icon=" {StaticResource iconUndo}" /> < MenuItem Name=" itemRedo" Command=" myCmd: Window1.RedoCommand" Header=" _Redo" Icon=" {StaticResource iconRedo}" /> < Separator> < /Separator> < MenuItem Name=" itemCut" Command=" myCmd: Window1.CutCommand" Header=" Cu_t" Icon=" {StaticResource iconCut}" /> < MenuItem Name=" itemCopy" Command=" myCmd: Window1.CopyCommand" Header=" _Copy" Icon=" {StaticResource iconCopy}" /> < MenuItem Name=" itemPaste" Header=" _Paste" Icon=" {StaticResource iconPaste}" /> < MenuItem Name=" itemDelete" Header=" De_lete" Icon=" {StaticResource iconDelete}" /> < Separator> < /Separator> < MenuItem Name=" itemFind" Click=" FindOnExecute" Header=" _Find..." InputGestureText=" Ctrl+F" Icon=" {StaticResource iconFind}" /> < MenuItem Name=" itemFindNext" Header=" Find _Next" /> < MenuItem Name=" itemReplace" Header=" _Replace..." /> < MenuItem Name=" itemGoTo" Header=" _Go To..." /> < Separator> < /Separator> < MenuItem Name=" itemSelectAll" Header=" Select _All" /> < /MenuItem> < MenuItem Header=" F_ormat" > < MenuItem Name=" itemFont" Click=" FontOnExecute" Header=" _Font..." Icon=" {StaticResource iconFont}" /> < Separator /> < MenuItem Name=" itemWordWrap" Click=" WordWrapOnExecute" Header=" _Word Wrap" IsCheckable=" True" IsChecked=" True" InputGestureText=" Ctrl+W" /> < /MenuItem> < MenuItem Header=" _Help" > < MenuItem Name=" itemAbout" Click=" AboutOnExecute" Header=" _About" /> < /MenuItem> < /Menu> <! -- Панель инструментов --> < ToolBarTray DockPanel.Dock=" Top" > < ToolBar> < Button Name=" btnNew" Click=" NewOnExecute" Width=" 23" Content=" {StaticResource iconNew}" /> < Button Name=" btnOpen" Click=" OpenOnExecute" Width=" 23" Content=" {StaticResource iconOpen}" /> < Button Name=" btnSave" Command=" myCmd: Window1.SaveCommand" Width=" 23" Content=" {StaticResource iconSave}" /> < /ToolBar> < ToolBar> < Button Name=" btnUndo" Command=" myCmd: Window1.UndoCommand" Width=" 23" Content=" {StaticResource iconUndo}" /> < Button Name=" btnRedo" Command=" myCmd: Window1.RedoCommand" Width=" 23" Content=" {StaticResource iconRedo}" /> < Separator /> < Button Name=" btnCut" Command=" myCmd: Window1.CutCommand" Width=" 23" Content=" {StaticResource iconCut}" /> < Button Name=" btnCopy" Command=" myCmd: Window1.CopyCommand" Width=" 23" Content=" {StaticResource iconCopy}" /> < Button Name=" btnPaste" Width=" 23" Content=" {StaticResource iconPaste}" /> < Button Name=" btnDelete" Width=" 23" Content=" {StaticResource iconDelete}" /> < /ToolBar> < ToolBar Header=" Find: " > < TextBox Width=" 100" /> < Button Name=" btnFind" Click=" FindOnExecute" Width=" 23" Content=" {StaticResource iconFind}" /> < /ToolBar> < /ToolBarTray> <! -- Строка состояния --> < StatusBar DockPanel.Dock=" Bottom" Height=" 32" Name=" statusBar" > < Label> Simulator Application is Loading< /Label> < Separator /> < ProgressBar Height=" 20" Width=" 100" IsIndeterminate=" True" /> < /StatusBar> <! -- Многострочное текстовое поле редактирования --> < TextBox TextWrapping=" Wrap" AcceptsReturn=" True" AcceptsTab=" True" VerticalScrollBarVisibility=" Auto" Name=" txtBox1" TextChanged=" txtBox1_TextChanged" HorizontalScrollBarVisibility=" Auto" > < TextBox.ContextMenu> < ContextMenu Width=" 100" > < MenuItem Name=" contextCut" Command=" myCmd: Window1.CutCommand" Header=" Cu_t" Icon=" {StaticResource iconCut}" /> < MenuItem Name=" contextCopy" Command=" myCmd: Window1.CopyCommand" Header=" _Copy" Icon=" {StaticResource iconCopy}" /> < MenuItem Name=" contextPaste" Header=" _Paste" Icon=" {StaticResource iconPaste}" /> < MenuItem Name=" contextDelete" Header=" De_lete" Icon=" {StaticResource iconDelete}" /> < /ContextMenu> < /TextBox.ContextMenu> < /TextBox> < /DockPanel> < /Window>Эта разметка визуально получилась достаточно широкой, ее лучше прежде скопировать, а потом разбирать.
В начальном состоянии источники команд являются недоступными, поскольку пока нет привязки к элементам визуального дерева и обработчикам. Исправим это и привяжем команды к коллекции CommandBindings окна Window1. Причем, в соответствии с намеченным планом выполним привязку одной части команд в коде, а остальной - в разметке. В месте привязки для каждого объекта привязки нужно указать имя команды, имя обработчика события Executed и имя обработчика события CanExecute для управления доступностью источников. Оба события всплывающие, поэтому местом привязки можно выбрать любой элемент маршрута, например, окно Window1. Это корень визуального дерева и ни одно всплывающее событие мимо него не пройдет. Обработчики события Executed для выполнения команд у нас есть, мы их уже создавали для обработки события Click. Например, для команды Save обработчик имеет имя SaveOnExecute и его сигнатура выглядит так private void SaveOnExecute(object sender, RoutedEventArgs e) { }Нам предстоит создать обработчики события CanExecute и мы разместим их в файле EnabledControls.cs. Они будут иметь несколько иную сигнатуру. Например, для команды Save такой обработчик должен иметь следующую заготовку private void SaveCanExecute(object sender, CanExecuteRoutedEventArgs e) { }
Теперь пришла пора выполнить саму привязку в соответствии с намеченным планом
Обратите внимание, что источники команд PageSetupCommand и GoToCommand должны быть доступны всегда, поэтому привяжем для них только обработчики события Executed
После того, как ссылка binding, которая пока единствественная адресовала объект, передаст адрес закрепленного за ней объекта в коллекцию CommandBindings элемента, этот объект станет адресоваться в двух местах: в коллекции и в ссылке. Поэтому такая ссылка станет уже излишней и ее можно будет использовать для присвоения адреса нового объекта. А коллекция так и будет продолжать адресовать брошенный ссылкой объект. В коде показано применение вариантов перегрузок конструктора класса CommandBinding и настройки свойств объекта.
Источники, к которым мы присоединили команды, по прежнему остаются недоступными, как после того, как мы к ним команды только присоединили. Но заметьте, что два источника: File/Page Setup... и Edit/Go To... открылись и функционируют, а для Go To даже клавиатурный жест Ctrl+G действует нормально. Это происходит потому, что мы для них не зарегистрировали обработчики событий CanExecute и они свободно вызывают обработчики, зарегистрированные в событии Executed, а остальные источники ждут разрешение на доступность. Создание таких разрешений в обработчиках CanExecute и составляет суть реализации логики доступности источников команд.
|