- •Лабораторная работа: События и команды в 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. Разработка простого блокнота с использованием механизма команд
- •Создание нового проекта из копии существующего
- •Краткий анализ задачи
- •Создание и привязка команд
- •Реализация логики доступности источников команд
- •Отображение позиции курсора в строке состояния
Обработка системной кнопки
Пока в приложение закрался один существенный недостаток. Когда документ содержит несохраненные изменения и пользователь завершает работу приложения по нашей команде Exit, то все в порядке - приложение извещает о необходимости их сохранить. Но когда окно закрывается по системной кнопке, то извещение отсутствует. Исправим это, для чего воспользуемся событием Closing. В отличии от Closing событие Closed возбудается, когда отменить закрытие окна уже невозможно, а можно только что-то доделать.
Присоедините к открывающему дескриптору окна Window1 в файле Window1.xaml обработчик события Closing, которое будет возбуждаться при попытке закрытия окна любым способом
<Window x:Class="Notepad1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1: Управление состоянием источников команд"
Width="500" Height="375"
MinWidth="500" MinHeight="375"
WindowStartupLocation="CenterScreen"
ResizeMode="CanResizeWithGrip"
Loaded="Window_Loaded"
Icon="Notepad.ico"
Closing="Window_Closing"
>
Заполните обработчик события Closing следующим кодом
private void Window_Closing(object sender,
System.ComponentModel.CancelEventArgs e)
{
if (!CheckModifiedAndSaveIt())
{
e.Cancel = true;
return; // Пользователь передумал выходить
}
}
Запустите приложение - теперь сообщение о несохраненных изменениях выводится и при попытке закрытия окна системной кнопкой
Обратите внимание, что при закрытии окна через наше меню задачей Exit на кнопку отказа от сохранения надо щелкать 2 раза. Это связано с тем, что в обработчике события Closing проверка повторяется. Значит при выходе через меню проверку в обработчике события Closing нужно блокировать с помощью флага.
Добавьте в класс Window1 поле-флаг _IsExitItem и модифицируйте соответствующим образом обработчики
bool _IsExitItem = false;
private void ExitOnExecute(object sender, RoutedEventArgs e)
{
if (!CheckModifiedAndSaveIt())
return; // Пользователь передумал выходить
_IsExitItem = true;
Close();
}
private void Window_Closing(object sender,
System.ComponentModel.CancelEventArgs e)
{
/*
// Эта проверка была бы надежнее
if(_IsExitItem)
return;
*/
// !_IsExitItem должен в условии стоять первым
if (!_IsExitItem && !CheckModifiedAndSaveIt())
{
e.Cancel = true;
_IsExitItem = false;
return; // Пользователь передумал выходить
}
}
В последнем обработчике есть один поучительный нюанс: если в условии проверку значения флага поставить последним, то код будет реагировать на наши нововведения. Это происходит потому, что логическое умножение проверяется компилятором слева направо до первого ложного значения. В нашем случае если флаг _IsExitItem==true, то функция CheckModifiedAndSaveIt() выполняться уже не будет. Такой код менее надежен, поскольку зависит от компилятора, да и мы (или сопровождающий программист) можем случайно переставить члены выражения местами. Поэтому лучше заменить этот код на более ясный, как показано в коментариях.
Запустите приложение и испытайте работу закрытия окна при несохраняемых изменениях
