Передача данных функциям, вызываемым в результате событий
Конечно, вы можете определить собственную сигнатуру для методов объекта-приемника, вызываемых источником, однако в .NET существует практически общепринятое правило, согласно которому функции приемника передаются два параметра:
Пример приводился ранее в главе 1. При размещении кнопки на форме генерировалась процедура события Click:
Private Sub Buttonl_Click(ByVal sender As System.Object.
ByValeAs System.EventArgs) Handles Button1.Click
End Sub
Параметры имеют следующий смысл:
Традиционно в VB источник (отправитель) события не идентифицировался в процедуре события. Единственным исключением были массивы управляющих элементов, когда конкретный элемент-отправитель выделялся из массива при помощи параметра-индекса. Смысл дополнительной объектной переменной sender в обобщенной процедуре события VB .NET становится очевидным, если вспомнить, что одна процедура может обрабатывать несколько событий, поступающих от разных объектов. Попробуйте вызвать встроенный метод ToString в приведенной выше процедуре события: MsgBox(sender.ToString) Результат будет выглядеть так:
Таким образом, процедура-обработчик может однозначно определить, какой объект был источником события.
В данном примере объект события е не представляет интереса, поскольку он не содержит сколько-нибудь полезной информации о событии. С другой стороны, в некоторых ситуациях он может пригодиться. Например, из объектной переменной класса MouseEventArgs можно узнать, в какой точке был сделан щелчок мышью.
В общем случае программист определяет собственные классы событий, производные от класса System. EventArgs и содержащие любую полезную информацию о событии (о том, как это делается, будет рассказано ниже).
Также обратите внимание на новое ключевое слово Hand! es в определении процедуры события. Как нетрудно догадаться, это ключевое слово указывает, какие события обрабатываются данной процедурой. Возможно, в данном примере ключевое слово Handl es выглядит излишним, однако оно предоставляет программисту дополнительные возможности, поскольку теперь обработчики события не обязаны обладать жестко заданными именами (фиксируются только сигнатуры). Следовательно, одна процедура может обрабатывать несколько событий, для чего в конец объявления процедуры включаются несколько секций Handl es. Новый подход обладает большей гибкостью по сравнению с массивами управляющих элементов, использовавшимися в прежних версиях VB (в VB .NET массивы элементов не поддерживаются).
Хотя IDE генерирует процедуры событий со стандартными именами, в VB .NET это уже не является обязательным требованием. Если процедура имеет правильный набор параметров и в ее заголовке присутствует ключевое слово Handles, эта процедура может использоваться для обработки событий. Пример:
Private Sub MyClickProcedure(ByVal sender As System.Object,_
ByValeAs System.EventArgs) Handles Buttonl.Click
Процедура MyClickProcedure может обрабатывать событие Buttonl. Click благодаря наличию правильных параметров. Она обрабатывает это событие, поскольку в заголовке указано ключевое слово Handles. Главное новшество заключается в явном указании обрабатываемых событий с ключевым словом Handles.
Рассмотрим другой пример. Допустим, предыдущий фрагмент был приведен к следующему виду:
Private Sub MyClickProcedureCByVal sender As System.Object._
ByVal e As System.EventArgs) Handles Buttonl.Click. Button2.Click._
mnuTHing.Click
Теперь одна процедура обрабатывает события сразу от двух разных кнопок и команды меню! В VB6 подобная универсальность была невозможна, поскольку в прежних версиях VB обработчики событий вызывались по имени элемента.Надеемся, читатель согласится с тем, что ключевое слово Handl es обладает значительно большим потенциалом, чем массивы управляющих элементов.