- •Лабораторная работа: События и команды в wpf
- •Обзор библиотечных событий
- •Упражнение 1. Обработка событий клавиатуры
- •События мыши
- •Упражнение 2. Прослушивание событий мыши
- •Упражнение 3. Создание и прослушивание пользовательского события
- •Обработчики уровня класса
- •Добавление информации в объект аргумента события
- •Задание для Упражнения 3
- •Модель команд
- •Объекты команд
- •Библиотечные классы команд
- •Присоединение команды к источнику
- •Привязка команды к прослушивающему элементу
- •Упражнение 4. Привязка команд в разметке
- •Перекрытие функций диспетчеризации событий
- •Прямой вызов команд
- •Упражнение 5. Привязка команд в процедурном коде
- •Жесты как источники команд
- •Добавление жестов в команду
- •Способ 1
- •Способ 2
- •Способ 3
- •Добавление жестов в прослушивающий элемент
- •Упражнение 6. Разработка простого блокнота без механизма команд
- •Создание главного меню
- •Добавление иконок
- •Создание логических ресурсов
- •Создание панели инструментов, строки состояния и рабочей области
- •Замена встроенного контекстного меню
- •Назначение ресурсов неразделяемыми
- •Замена иконок на прозрачные
- •Отключение встроенных команд
- •Подключение иконки приложения
- •Распределение класса по нескольким файлам и создание вспомогательных функций
- •Размещение вариантов заголовков окна в ресурсах приложения
- •Создание заготовок обработчиков
- •Регистрация обработчиков в разметке
- •Реализация обработчиков раздела меню File
- •Обработка системной кнопки
- •Реализация части обработчиков раздела меню Edit
- •Разработка и кодирование диалогового окна Find and Replace
- •Кодирование функциональности Find and Replace в основном окне
- •Подключение функциональности Find and Replace к источникам задач
- •Разработка диалогового окна Go To
- •Применение вложенных ресурсов
- •Подключение функциональности Go To к основному окну
- •Прочие задачи
- •Принудительная перерисовка окна
- •Добавление жестов
- •Логика отключения источников задач
- •Реализация логики отключения источников задачи Save
- •Упражнение 7. Разработка простого блокнота с использованием механизма команд
- •Создание нового проекта из копии существующего
- •Краткий анализ задачи
- •Создание и привязка команд
- •Реализация логики доступности источников команд
- •Отображение позиции курсора в строке состояния
Добавление иконок
Теперь добавим к пунктам меню иконки, которые можно взять в архиве VS2008ImageLibrary.zip, устанавливаемом на компьютер вместе с VS-2008 и находящимся в каталоге Program Files\Microsoft Visual Studio 9.0\Common7\VS2008ImageLibrary\1033. Мы будем использовать иконки из папки архива VS2008ImageLibrary\Actions\24bitcolor bitmaps. Для удобства они скопированы в каталог Source данной работы.
В панели Solution Explorer вызовите контекстное меню для корня проекта Notepad1 и добавьте командой Add/New Folder новую папку с именем Images
Вызовите для папки Images контекстное меню и командой Add/Existing Item скопируйте в нее иконки с расширением .bmp из папки Source:
Подключите иконку NewDocument.bmp к пункту меню File/New, модифицировав разметку для этого элемента так
Было <MenuItem Header="_New" InputGestureText="Ctrl+N">
</MenuItem>
Стало <MenuItem Header="_New" InputGestureText="Ctrl+N">
<MenuItem.Icon>
<Image Source="Images/NewDocument.bmp" Width="16" Height="16" />
</MenuItem.Icon>
</MenuItem>
Запустите приложение и убедитесь, что иконка появилась слева от названия пункта меню New
Здесь есть один недостаток, который бросается в глаза - фон иконки имеет цвет Magenta. В Windows Forms фон устраняется установкой параметра ImageTransparentColor в значение цвета, который система будет считать прозрачным. В WPF для нейтрализации фона можно применить другой механизм, задействующий параметр OpacityMask, но пока мы оставим все как есть.
Создание логических ресурсов
Если в каждый элемент MenuItem мы будем встраивать дескриптор <MenuItem.Icon> с элементом Image, то разметка сильно разбухнет и станет нечитабельным. Чтобы сделать код более элегантным, воспользуемся новым механизмом WPF - логическими ресурсами. Ресурсы хороши тем, что их можно использовать многократно в различных местах приложения. В нашем приложении одни и те же иконки понадобятся в меню, панели инструментов и контекстном меню.
Каждый элемент, производный от класса FrameworkElement, включая окно Window, наследует от FrameworkElement коллекцию Resources типа словаря ресурсов System.Windows. ResourceDictionary. В эту коллекцию можно помещать описания пар ключ-объект, ссылки на которые потом можно подключать к элементам управления для встраивания объектов. Такой прием называется расширением разметки интерфейсных элементов.
Обязательным элементом при объявлении и использовании ресурса является ключ x:Key="идентификатор_ключа", которому можно присваивать произвольное имя. В пределах одной коллекции ключи должны быть уникальными. Использование ссылки на ресурс для свойства элемента выполняется по синтаксису
Свойство="{StaticResource идентификатор_ключа}"
или
Свойство="{DynamicResource идентификатор_ключа}"
Синтаксический анализатор разметки XAML присвоит свойству объявленный в ресурсе объект. Если применяется ссылка на статический ресурс, то объявление ресурса должно предшествовать его использованию. Встретив ссылку на ресурс анализатор начинает поиск объекта с заданным ключом вначале в коллекции Resources того элемента, где расположена ссылка. Не найдя нужную пару анализатор поднимается на уровень выше и просматривает коллекцию родительского элемента и так далее, пока не будет найдена соответствующая ссылке пара. Таким образом, ресурсы можно объявлять в любом элементе, но лучше сосредоточить их в коллекции <Window.Resources> окна или <Application.Resources> приложения.
Добавьте после открывающего дескриптора окна объявление логического ресурса, а в самозакрывающемся дескрипторе элемена меню - его использование по ключу
<Window x:Class="Notepad1.Window1"
...............................................
>
<Window.Resources>
<!-- File -->
<Image x:Key="iconNew" Source="Images/NewDocument.bmp" Width="16" Height="16" />
</Window.Resources>
<DockPanel LastChildFill="True">
<!-- Меню -->
<Menu DockPanel.Dock="Top">
<MenuItem Header="_File">
<!-- Сокращенные варианты подключения иконок с использованием статических ресурсов -->
<MenuItem Header="_New" InputGestureText="Ctrl+N" Icon="{StaticResource iconNew}" />
...............................................
</MenuItem>
...............................................
</Menu>
</DockPanel>
</Window>
Запустите приложение и убедитесь, что иконка присутствует слева от названия пункта меню New, но разметка элемента меню стала значительно короче
Расширьте объявление ресурсов на все иконки
<Window.Resources>
<!-- File -->
<Image x:Key="iconNew" Source="Images/NewDocument.bmp" Width="16" Height="16" />
<Image x:Key="iconOpen" Source="Images/Open.bmp" Width="16" Height="16" />
<Image x:Key="iconSave" Source="Images/Save.bmp" Width="16" Height="16" />
<Image x:Key="iconPageSetup" Source="Images/PrintSetup.bmp" Width="16" Height="16" />
<Image x:Key="iconPrintPreview" Source="Images/PrintPreview.bmp" Width="16" Height="16" />
<Image x:Key="iconPrint" Source="Images/Print.bmp" Width="16" Height="16" />
<!-- Edit -->
<Image x:Key="iconUndo" Source="Images/Edit_Undo.bmp" Width="16" Height="16" />
<Image x:Key="iconRedo" Source="Images/Edit_Redo.bmp" Width="16" Height="16" />
<Image x:Key="iconCut" Source="Images/Cut.bmp" Width="16" Height="16" />
<Image x:Key="iconCopy" Source="Images/Copy.bmp" Width="16" Height="16" />
<Image x:Key="iconPaste" Source="Images/Paste.bmp" Width="16" Height="16" />
<Image x:Key="iconDelete" Source="Images/Delete.bmp" Width="16" Height="16" />
<Image x:Key="iconFind" Source="Images/Find.bmp" Width="16" Height="16" />
<Image x:Key="iconFont" Source="Images/Font.bmp" Width="16" Height="16" />
</Window.Resources>
Дополните разметку создания главного меню ссылками на ресурс объекта рисунка для свойства Icon
<!-- Меню -->
<Menu DockPanel.Dock="Top">
<MenuItem Header="_File">
<!-- Сокращенные варианты подключения иконок с использованием статических ресурсов -->
<MenuItem Header="_New" InputGestureText="Ctrl+N" Icon="{StaticResource iconNew}" />
<MenuItem Header="_Open..." InputGestureText="Ctrl+O" Icon="{StaticResource iconOpen}" />
<MenuItem Header="_Save" InputGestureText="Ctrl+S" Icon="{StaticResource iconSave}" />
<MenuItem Header="Save _As..." />
<Separator />
<MenuItem Header="Page Set_up..." Icon="{StaticResource iconPageSetup}" />
<MenuItem Header="P_rint Preview" InputGestureText="Ctrl+F2" Icon="{StaticResource iconPrintPreview}" />
<MenuItem Header="_Print..." InputGestureText="Ctrl+P" Icon="{StaticResource iconPrint}" />
<Separator />
<MenuItem Header="E_xit" />
</MenuItem>
<MenuItem Header="_Edit">
<MenuItem Header="_Undo" InputGestureText="Ctrl+Z" Icon="{StaticResource iconUndo}" />
<MenuItem Header="_Redo" InputGestureText="Ctrl+Y" Icon="{StaticResource iconRedo}" />
<Separator></Separator>
<MenuItem Header="Cu_t" InputGestureText="Ctrl+X" Icon="{StaticResource iconCut}" />
<MenuItem Header="_Copy" InputGestureText="Ctrl+C" Icon="{StaticResource iconCopy}" />
<MenuItem Header="_Paste" InputGestureText="Ctrl+V" Icon="{StaticResource iconPaste}" />
<MenuItem Header="De_lete" InputGestureText="Del" Icon="{StaticResource iconDelete}" />
<Separator></Separator>
<MenuItem Header="_Find..." InputGestureText="Ctrl+F" Icon="{StaticResource iconFind}" />
<MenuItem Header="Find _Next" InputGestureText="F3" />
<MenuItem Header="_Replace..." InputGestureText="Ctrl+H" />
<MenuItem Header="_Go To..." InputGestureText="Ctrl+G" />
<Separator></Separator>
<MenuItem Header="Select _All" InputGestureText="Ctrl+A" />
</MenuItem>
<MenuItem Header="F_ormat">
<MenuItem Header="_Font..." Icon="{StaticResource iconFont}" />
<Separator />
<MenuItem Header="_Word Wrap" IsCheckable="True" IsChecked="True" InputGestureText="Ctrl+W" />
</MenuItem>
<MenuItem Header="_Help">
<MenuItem Header="_About" />
</MenuItem>
</Menu>
Запустите приложение и проверьте наличие иконок в элементах главного меню
