Cамоучитель по VB.NET

мотор сузуки продажа


 

Простейшее инициирование событий


Давайте вернемся к простому классу Empl oyee и подробно, шаг за шагом разберем все, что необходимо сделать для определения и инициирования событий. Предположим, событие должно инициироваться при попытке увеличения заработной платы более чем на 10 процентов без ввода пароля. В главе 4 метод RaiseSalary выглядел так:

Public Overloads Sub RaiseSalary(ByVal percent As Decimal)

If percent > LIMIT Then

' Операция запрещена - Необходим пароль

Console.WriteLine("MUST HAVE PASSWORD TO RAISE SALARY " & _

"MORE THAN LIMIT!!!!") Else

m_Sa1ary =(1 + percent) * m_salary

End If

End Sub

Вместо выделенной команды, выводящей текстовое сообщение на консоль, должно инициироваться событие. Задача решается в несколько этапов. В простейшем случае в классе сначала объявляется открытая переменная с ключевым словом Event, с указанием имени события и его параметров. Например, следующая строка весьма близка к синтаксису VB6: Public Event SalarySecurityEventdnessage as String) В этой строке объявляется открытое событие с параметром строкового типа.

События обычно объявляются с модификатором Public, никогда не возвращают значений и могут получать параметры произвольного типа, кроме ParamArray.

После того как переменная события будет определена, событие инициируется командой следующего вида (впрочем, для того, чтобы событие действительно произошло, потребуются еще кое-какие дополнительные действия):

RaiseEvent SalarySecurityEventC'MUST HAVE PASSWORD TO RAISE " & _

"Salary MORE THAN LIMIT!! !!")

Однако из этого не следует, что для любого события следует ограничиваться одним строковым параметром. В соответствии с парадигмой программирования .NET в качестве параметров любого события передается объект-источник и информация о событии, инкапсулированная в объекте события. На первых порах вполне достаточно объявления вида

Public Event SalarySecurityEvent(ByVal who As Employee, ByVale As system.EventArgs)

Событие инициируется следующей командой RaiseEvent:

RaiseEvent SalarySecurityEvent(Me,New System.EventArgs())

Хотя события обычно объявляются открытыми, это не является обязательным требованием — событие может иметь любой модификатор уровня доступа. Закрытыми (Private) объявляются события, представляющие интерес только для объектов этого класса, а защищенные (Protected) события также могут обрабатываться объектами производных классов. Допускается даже объявление общих (Shared) событий, которые, как и общие члены классов, существуют на уровне класса в целом, а не его отдельных членов (в частности, общие методы могут инициировать только общие события).

По сигнатуре события приемник узнает, от какого источника поступило событие (в данном примере это объект-работник, которому попытались неправильно повысить заработную плату); сам объект передается в виде ключевого слова Me. Впрочем, приведенное объявление не использует возможностей передачи данных в переменной события е. Вскоре мы разработаем класс, производный от System. EventArgs, в объектах которого будет содержаться строка предупреждения вместе с данными о попытке повышения заработной платы.

 

Подключение приемников к источнику

В нашем распоряжении имеется весь код, необходимый для рассылки событий, но пока нет ни одного заинтересованного получателя. Существует несколько способов, которыми класс может сообщить VB .NET о своем желании получать события от другого класса. Простейший способ очень похож на тот, который использовался в VB6: на уровне модуля (или класса) объявляется переменная класса-приемника с ключевым словом WithEvents. Например, если включить в класс следующую строку, не входящую ни в один из членов: Private WithEvents anEmployee As Employee

объекты этого класса становятся потенциальными приемниками событий, инициируемых классом Employee. Обратите особое внимание на некоторые особенности этого объявления:

  • Класс источника должен быть указан явно, объявления вида As Object недопустимы.
  • Объявление располагается на уровне модуля или класса и не содержит ключевого слова New.
После включения этой строки в программу объектная переменная anEmpl oyee может использоваться всюду, где вас интересует событие SalarySecurityEvent. Как показано на рис. 6.2, IDE автоматически создает обработчик события с именем, построенным по схеме А_В, для каждой объектной переменной, объявленной с ключевым словом Wi thEvents. Чтобы вызвать автоматически сгенерированный «скелет» события, достаточно выбрать его в раскрывающемся списке, как на рис. 6.2.

 

Все вместе

А теперь давайте объединим все сказанное на практическом примере. Создайте консольное приложение и включите следующий фрагмент в первый (стартовый) модуль:

Module Modulel

Private WithEvents anEmployee As EmployeeWithEvents

Sub Main()

Dim tom As New EmployeeWithEvents("Tom". 100000)

anEmployee = tom

Console.WriteLine(tom.TheName & "has salary " & tom.Salary)

anEmployee.RaiseSalary(0.2D) ' Суффикс D - признак типа Decimal

Console.WriteLinettom.TheName & "still has salary " & tom.Salary)

Console.WritelineC'Please press the Enter key")

Console.ReadLine() End Sub End Module

Рис. 6.2. Автоматически сгенерированный код обработчика события

Теперь выберите в раскрывающемся списке метод anEmployee_SalarySecurityEvent. Исходный текст этого метода приведен ниже (для удобства чтения он разбит на несколько строк, а ключевая секция Handles выделена жирным шрифтом):

Public Sub anEmployee_SalarySecur1tyEvent(ByVal Sender As

Event_Handling_I.EmployeeWithEvents, ByValeAs System.EventArgs) Handles

anEmployee.SalarySecurityEverrt

End Sub

End Module

Обратите внимание на символ подчеркивания, добавленный VB .NET между именем переменной с ключевым словом WithEvents (anEmployee) и именем события (SalarySecurityEvent), — с ним обработчик внешне почти не отличается от процедур событий в VB6.

Также обратите внимание на идентификацию объекта Sender полным именем (в формате пространство_имен. имя_класса). Наличие дополнительных символов подчеркивания в пространстве имен объясняется тем, что пробелы в них не разрешены, поэтому VB .NET автоматически преобразует имя решения «Event Handling 1» в «Event_Handling_l» (рис. 6.3). Наконец, ключевое слово Handles сообщает исполнительной среде, какое событие обрабатывается этой процедурой.

Рис. 6.3. Окно свойств решения с обработкой событий

Чтобы пример стал более интересным, вместо простого вывода в консольное окно 'мы включим в процедуру события команду вызова диалогового окна:

Public Sub anEmployee_SalarySecurityEvent(ByVal Sender As

Event_Handling_I.EmployeeWithEvents. ByVal e As System.EventArgs)

Handles anEmployee.SalarySecurityEvent

MsgBox(Sender.TheName &"had an improper salary raise attempted!")

End Sub

От приемника событий мы переходим к источнику. В класс Employee из главы 4 необходимо внести два изменения, выделенные в следующем листинге жирным шрифтом:

Public Class EmployeeWithEvents

Private m_Name As String

Private m_Salary As Decimal

Private Const LIMIT As Decimal =0.1D

Public Event SalarySecurityEventCByVal Sender As

EmployeeWithEvents,ByVal e As EventArgs)

Public Sub NewCByVal

aName As String. ByVal curSalary As Decimal)

m_Name = aName

m_Salary = curSalary

End Sub Readonly Property TheName() As String

Get

Return m_Name

End Get

End Property Readonly Property Salary() As Decimal s,

Get

Return m_Salary

End Get ' '

End Property

Public Overloads Sub RaiseSalary(ByVal Percent As Decimal)

If Percent > LIMIT'Then

'Операция запрещена - необходим пароль

RaiseEvent SalarySecurityEventtMe, New System.EventArgs())

Else

m_Sa1ary = (1 + Percent) * m_Salary

End If

End Sub

Public Overloads Sub RaiseSalary(ByVal Percent As Decimal.

ByVal Password As String)

If Password = "special" Then

m_Salary = (1 + Percent) * m_Salary

End If

End Sub

End Class

Первый выделенный фрагмент объявляет событие, а второй инициирует его при попытке недопустимого повышения зарплаты.

Примерный результат запуска программы показан на рис. 6.4. При нажатии кнопки ОК окно сообщения исчезает, и в консольном окне выводится строка, из которой видно, что зарплата Тома не изменилась.

Переменные WithEvents потребляют системные ресурсы. Как только такая перемен-ная становится ненужной, присвойте ей Nothing.

Рис. 6.4. Окно сообщения, вызываемое при обработке события

 

Назад Начало Вперед