При разработке программ (это особенно очевидно для оконных приложений) довольно часто возникает потребность в том, чтобы в данной части программы как-то среагировать на событие, произошедшее в другой части программы. Например, при нажатии на клавишу мыши вывести какое-либо сообщение в окне программы или графическое изображение, т.е. здесь при нажатии на клавишу происходит событие (event) и на него реагирует специальная функция — обработчик этого событий (event handler).
Когда говорят о событиях, то часто используют такие термины. Объект, который генерирует событие, называют источником события, объект, получающий события, называют приёмником. Метод приёмника, который должен реагировать на событие, называется обработчиком события.
Нередко применяют и другие термины. Объект, который генерирует событие, называется издателем. Говорят, что издатель публикует событие, на которое должны подписаться подписчики — объекты, реагирующие на событие издателя.
Если сопоставить понятие события и понятие делегата, то напрашивается мысль о сходстве двух этих понятий. Действительно, событие является частным случаем делегата. Но в отличие от делегата событие всегда генерируется для объекта класса.
Для работы с событием в программе необходимо выполнить следующие действия:
1)Объявить тип делегата события:
delegate тип_возвращаемого_значения тип_делегата_события (список_формальных_параметров);
где
delegate — ключевое слово, означающее, что в данном предложении даётся определения класса-делегата. Перед этим словом, естественно, может быть указан тип доступа, например: public;
тип_возвращаемого_значения — это тип результата, который должна возвращать делегируемая функция;
тип_делегата_события — это имя типа делегата, т.е. название класса-делегата, необходимого для работы с событиями;
список_формальных_параметров — список формальных параметров делегируемой функции, записывается по общим правилам как для любого метода.
2)Объявить ссылку на событие:
event тип_делегата_события ссылка_на_событие;
где
event — ключевое слово на языке C#, определяющее событие;
тип_делегата_события — это имя типа делегата, т.е. название класса-делегата, необходимого для работы с событиями;
ссылка_на_событие — имя ссылки на событие.
Ссылка на событие чаще всего объявляется в классе — источнике события, но может объявляться и вне этого класса.
3)В классе — источнике события необходимо объявить открытый метод, в котором будет активироваться событие. Формат этого метода следующий:
public void имя_метода()
{
if(ссылка_на_событие != null)
{
ссылка_на_событие();
}
}
В этом методе обязательно должен присутствовать условный оператор. Нельзя активировать событие до тех пор, пока не будет установлена связь между источником и приёмником события!
4)В классе-приёмнике события необходимо записать метод по обработке события.
5)Теперь можно использовать событие. Создаём объект-источник и объект-приёмник, регистрируем обработчик события и генерируем событие. Обработчик события должен его выполнить.
Пример. Создадим простейший пример программы, в которой объект класса A (это источник) будет генерировать событие, а объект класса B (это приёмник) — обрабатывать данное событие.
Текст программы:
using System;
namespace Prim_Event
{
public delegate void Del();
class A
{
public event Del genEv;
public void F()
{
if(genEv != null)
{
genEv();
}
}
}
class B
{
public void HandlerEv()
{
Console.WriteLine("Объект класса B получил сообщение");
}
}
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Тест событие:\n");
// 1)Создаём объект-источник события:
A x = new A();
// 2)Создаём объект-приёмник события:
B y = new B();
// 3)Добавляем обработчик события
// (здесь объект y подписывается на сообщение
// объекта x и гарантирует, что будет на событие
// genEv выполнять обработчик HandlerEv)
x.genEv += new Del(y.HandlerEv);
// 4)Генирируем событие:
x.F();
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}
Результаты работы программы:
Тест событие:
Объект класса B получил сообщение
Press any key to continue . . .
Замечание. Разработчиками библиотеки .NET создано большое количество стандартных делегатов, предназначенных для реализации механизма обработки событий. Обычно они оформлены по таким правилам:
имя делегата заканчивается суффиксом EventHandler;
делегат имеет два параметра: первый параметр имеет тип object и определяет объект-источник, второй параметр имеет тип EventArgs и служит для задания дополнительной информации.
Как следствие, обработчики событий имеют вид:
public void Имя_обработчика(object sendler, EventArgs e)
{
// необходимые действия
}
Чаще всего в обработчике используется второй параметр, например, в типичном обработчике события по перерисовке окна формы, используя второй параметр, мы добираемся до полотна (свойство Graphics), на которое выводится изображение:
void MainFormPaint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
// перерисовка объектов в окне формы,
// например, рисуем линию:
g.DrawLine(new Pen(Color.Red), 10,10,100,50);
}
|
|
|