| Украина, Киев |
Пользовательские элементы управления
Переопределение наследуемого от Control виртуального метода диспетчеризации события Click
Большинство библиотечных классов, в которых определены события, имеют соответствующие одноименные виртуальные методы диспетчеризации этих событий с приставкой On. Эти методы можно переопределять в классах-наследниках, дополняя нужным кодом. Когда среда исполнения возбуждает событие для какого-то элемента управления, вызывается метод диспечеризации, который адресуется в направлении от объекта формы к этому элементу по цепочки наследования в соответствии с таблицей виртуальных функций.
Над библиотечным элементом управления всегда можно надстроить класс-потомок, в котором перехватить этот виртуальный метод и обработать нужным образом. При этом, если в переопределенном методе не продолжить вызов виртуального метода диспетчеризации события в сторону базового класса, то ни один подписавшийся на это событие обработчик не сработает.
Воспользуемся этой возможностью в нашем классе расширения кнопки, упаковав переопределение метода в отдельную часть класса BeepButton.
namespace MyCompany.UserControls
{
partial class BeepButton
{
// Переопределяем виртуальный метод диспетчеризации
// класса Control (задействуется наследуемый метод
// диспетчеризации класса кнопки)
protected override void OnClick(EventArgs e)
{
// Проиграть системный звук
SystemSounds.Exclamation.Play();// Сочный через внешние динамики
//SystemSounds.Beep.Play(); // Простой через внешние динамики
//System.Console.Beep(); // Простой через внутренний динамик
// Подняться до базового класса Control,
// чтобы сгенерировать его событие Click и
// запустить наш будущий обработчик ButtonOnClick
base.OnClick(e);
}
}
}
Листинг
19.2.
Переопределение метода диспетчеризации OnClick() в файле BeepButton.cs
В переопределенном методе диспетчеризации события Click кнопки мы предусмотрели вызов базового метода диспетчеризации непосредственно кнопки Button, чтобы дать возможность клиентам нашего класса BeepButton подписать свои обработчики на это событие. Событие Click, в свою очередь, унаследовано классом Button от класса Control и генерируется его методом OnClick примерно так
protected virtual void OnClick(EventArgs args)
{
//...
// Если хоть один обработчик зарегистрирован
if (Click != null)
Click(this, args);
//...
}Испытание кнопки BeepButton мы проведем позднее, разработав для этого тестовую исполнимую Windows -сборку.
Упражнение 2. Проектирование диалогового окна сообщений MyDialogBox
Для целей выдачи пользователю простых сообщений существует стандартное диалоговое окно, поддерживаемое классом System.Windows.Forms. MessageBox. Но в целях тренировки в данном разделе мы спроектируем собственное простое диалоговое окно сообщений с именем MyDialogBox, которое и будет вызываться из обработчика события Click нашей кнопки, если на него подпишется клиент компонента BeepButton.
Создание диалогового окна будет состоять из трех шагов:
- Создание самой формы диалогового окна (класс MyDialogForm )
- Размещение на форме интерфейсных элементов пользователя
- Создание класса MyDialogBox.cs, управляющего диалоговым окном
-
В панели Solution Explorer выделите узел проекта UserControls и
командой Add/Windows Form добавьте к компоненту
файл формы с именем MyDialogForm.cs
-
Удалите
из узла References лишние добавленные мастером
ссылки на библиотечные сборки System.Data и System.Xml
-
Удалите
соответствующие инструкции using подключения пространств
имен в начале файла MyDialogForm.cs
-
Настройте
форму MyDialogForm в соответствии с таблицей
-
Из
свитка Containers панели инструментов Toolbox поместите
на форму компоновочную панель FlowLayoutPanel и
настройти ее в соответствии с таблицей
Эта панель будет следить за размещением своих дочерних элементов в соответствии с настройками.
-
Поместите
внутрь экземпляра компоновочной панели flow из
свитка Common Controls текстовую метку Label и
настройте ее свойства в соответствии с таблицей
Для того, чтобы объект lblMessage был доступен из метода класса MyDialogBox, при его создании мы сделали его общедоступным.
-
Поместите
внутрь компоновочной панели flow из свитка Common
Controls кнопку Button и
настройте ее свойства в соответствии с таблицей
Свойству дочерних кнопок формы DialogResult можно присвоить любое значение из перечисления System.Windows.Forms. DialogResult ( Abort, Cancel, Ignore, No, None, OK, Retry, 26_23 ). Оно и будет возвращено функцией ShowDialog() формы, если пользователь выберет именно эту кнопку.
Мы создали интерфейсный класс диалогового окна. Теперь нужно создать управляющий класс, в котором мы будем создавать экземпляр интерфейсного класса диалогового окна и вызывать его на экран.
-
В панели Solution Explorer выделите узел проекта UserControls и,
выполнив команду меню Project/Add Class,
добавьте к проекту новый класс с именем MyDialogBox
-
Заполните
файл MyDialogBox.cs следующим кодом
using System;
using System.Windows.Forms;
namespace MyCompany.UserControls
{
// Наше диалоговое окно сообщения
public class MyDialogBox
{
public static DialogResult Show(string strMessage, string strCaption)
{
// Создаем диалоговое окно
MyDialogForm frm = new MyDialogForm();
// Заголовок окна
frm.Text = strCaption;
// Содержимое текстовой метки
frm.lblMessage.Text = strMessage;
// Отобразить диалоговое окно в модальном режиме,
// а после его закрытия вернуть выбор пользователя
// вызывающему коду
return frm.ShowDialog();// Выполняем диалоговое окно
// и возвращаем статус нажатой кнопки
}
}
}
Листинг
19.4.
Код управления диалоговым окном в файле MyDialogBox.cs
Класс MyDialogBox нужно объявить с модификатором public, чтобы он был виден в клиентских сборках. Объявление метода Show() в классе MyDialogBox как статического позволяет его вызывать без создания экземпляра этого класса в клиенте. Через аргументы метода Show() можно задавать заголовок диалогового окна и содержимое текстовой метки lblMessage, как это принято в библиотечном классе System.Windows.Forms.MessageBox.
Теперь осталось собрать все вместе и испытать на тестовом приложении, но прежде нужно откомпилировать проект UserControls и убедиться, что нет синтаксических ошибок.


