События

Последнее обновление: 30.10.2015

Хотя наши делегаты прекрасно выполняют возложенную на них функцию, но в языке VB.NET для этих же целей предусмотрены более простые и удобные конструкции под названием события. Итак, продолжим работу с классом Client из прошлой главы и изменим его следующим образом:

Public Class Client
    Inherits Person
    Implements IAccount

    'Объявляем делегат
    Public Delegate Sub AccountStateHandler(message As String)
    'Событие, возникающее при выводе денег
    Public Event Withdrowed As AccountStateHandler
    'Событие возникающее при добавление на счет
    Public Event Added(sum As Integer)

    'Переменная для хранения суммы
    Dim _sum As Integer
    'Переменная для хранения процента
    Dim _procentage As Integer

    Public Property Bank As String

    'Текущая сумма на счете
    ReadOnly Property CurentSum() As Integer Implements IAccount.CurentSum
        Get
            Return _sum
        End Get
    End Property
    'Метод для добавления денег на счет
    Sub Put(sum As Integer) Implements IAccount.Put
        _sum += sum
        RaiseEvent Added(sum)
    End Sub
    'Метод для снятия денег со счета
    Sub Withdraw(sum As Integer) Implements IAccount.Withdraw
        If sum <= CurentSum Then
            _sum -= sum
            RaiseEvent Withdrowed("Сумма " & sum & " снята со счета")
        Else
            RaiseEvent Withdrowed("Недостаточно денег на счете")
        End If
    End Sub
    'Процент начислений
    ReadOnly Property Procentage() As Integer Implements IAccount.Procentage
        Get
            Return _procentage
        End Get
    End Property

    Public Overrides Sub Display()
        Console.WriteLine(FirstName & " " & LastName & " has an account in bank " & Bank)
    End Sub

    Public Sub New(fName As String, lName As String, _bank As String, _sum As Integer)
        MyBase.New(fName, lName)
        Bank = _bank
        Me._sum = _sum
    End Sub

End Class

Здесь мы сделали несколько изменений по сравнению с предыдущей версией класса. Во-первых, мы убрали переменную делегата и методы регистрации и отмены регистрации метода делегата. Во-вторых. мы добавили два события. События объявляются с помощью ключевого слова Event. Поскольку первое событие Withdrowed объявлено как экземпляр делегата AccountStateHandler, то для его обработки потребуется метод, принимающий строку в качестве параметра. Для второго события Added делегат не задан, поэтому мы указываем параметры в объявлении события. Поэтому метод, обрабатывающий данное событие, должен будет принимать в качестве параметра значение типа Integer. Вместо вызова делегатов мы устанавливаем вызовы событий с помощью ключевого слова RaiseEvent, передавая в события значения для параметров.

Теперь обработаем события в основной программе:

Sub Main()

    Dim client1 As New Client("John", "Thompson", "City Bank", 200)
		
	'Добавляем обработчики события
    AddHandler client1.Withdrowed, New Client.AccountStateHandler(AddressOf Color_Message)
    AddHandler client1.Added, AddressOf Show_Message

    client1.Withdraw(100)
	'Удаляем обработчик события
    RemoveHandler client1.Withdrowed, AddressOf Color_Message

    client1.Withdraw(50)
    client1.Put(150)

    Console.ReadLine()
End Sub

Private Sub Show_Message(sum As Integer)
    Console.WriteLine("На счет поступило {0} $", sum)
End Sub

Private Sub Color_Message(message As String)
    'Устанавливаем красный цвет символов
    Console.ForegroundColor = ConsoleColor.Red
    Console.WriteLine(message)
    'Сбрасываем настройки цвета
    Console.ResetColor()
End Sub

Добавление обработчиков события происходит с помощью ключевого слова AddHandler, после которого идет имя события, которое будет обрабатываться. Далее мы можем указать делегат, либо использовать сокращенную запись добавления обработчика события. После ключевого слова AddressOf мы указываем метод, который и будет обрабатывать событие. Удаление обработчика события происходит подобным образом с помощью ключевого слова RemoveHandler. После удаления обработчика данное событие не будет обрабатываться методом Color_Message.

Существует еще один способ обработки события - с помощью ключевого слова Handles:

Module Module1

    Dim WithEvents client2 As New Client("Gomer", "Simpson", "City Bank", 200)
	
	Private Sub Color_Message2(message As String) Handles client2.Withdrowed
        'Устанавливаем красный цвет символов
        Console.ForegroundColor = ConsoleColor.Red
        Console.WriteLine(message)
        'Сбрасываем настройки цвета
        Console.ResetColor()
    End Sub
End Module

В этом случае мы объявляем переменную, у которой будем обрабатывать события, с помощью ключевого слова WithEvent, которое идет сразу после модификатора доступа. При чем так объявить переменную мы можем только на уровне модуля или класса, но не на уровне процедуры или функции. После объявления с помощью WithEvent мы можем обрабатывать событие, написав в объявлении метода после параметров ключевое слово Handles, после которого следует событие объекта. Обратите внимание. что такое объявление обработчика события доступно только для одиночного объекта, то есть мы не можем объявить целый массив следующим образом:

Dim WithEvents clients(4) As Client

В этом случае нам придется добавлять обработчики через AddHandler.

Говоря о событиях, нельзя не затронуть еще одну тему. Как правило, одним из наиболее распространенных вопросов новичков, состоит в том, а что такое параметр e в обработчике кнопке ( Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click), да и в других событиях. Ответ на этот вопрос, как правило, следующий: e является объектом класса EventArgs, который содержит все данные события. Добавим и в нашу программу подобный класс:

Public Class AccountEventArgs
    Inherits EventArgs
    'Сообщение
    Public ReadOnly message As String
    'Сумма, на которую изменился счет
    Public ReadOnly sum As Integer
    Sub New(_message As String, _sum As Integer)
        message = _message
        sum = _sum
    End Sub
End Class

Здесь все просто - класс наследуется от класса EventArgs. Этот класс имеет два поля: одно для выводимого сообщения, и другое для хранения величины, на которую изменился счет. С учетом этого класса изменим класс Client:

Public Class Client
    Inherits Person
    Implements IAccount

    'Объявляем делегат
    Public Delegate Sub AccountStateHandler(sender As Object, e As AccountEventArgs)
    'Событие, возникающее при выводе денег
    Public Event Withdrowed As AccountStateHandler
    'Событие возникающее при добавление на счет
    Public Event Added(sender As Object, e As AccountEventArgs)

    'Переменная для хранения суммы
    Dim _sum As Integer
    'Переменная для хранения процента
    Dim _procentage As Integer

    Public Property Bank As String

    'Текущая сумма на счете
    ReadOnly Property CurentSum() As Integer Implements IAccount.CurentSum
        Get
            Return _sum
        End Get
    End Property
    'Метод для добавления денег на счет
    Sub Put(sum As Integer) Implements IAccount.Put
        _sum += sum
        RaiseEvent Added(Me, New AccountEventArgs("Деньги добавлены на счет", sum))
    End Sub
    'Метод для снятия денег со счета
    Sub Withdraw(sum As Integer) Implements IAccount.Withdraw
        If sum <= CurentSum Then
            _sum -= sum
            RaiseEvent Withdrowed(Me, New AccountEventArgs("Деньги сняты со счета", sum))
        Else
            RaiseEvent Withdrowed(Me, New AccountEventArgs("Недостаточно денег на счете. Операция недействительна", sum))
        End If
    End Sub
    'Процент начислений
    ReadOnly Property Procentage() As Integer Implements IAccount.Procentage
        Get
            Return _procentage
        End Get
    End Property

    Public Overrides Sub Display()
        Console.WriteLine(FirstName & " " & LastName & " has an account in bank " & Bank)
    End Sub

    Public Sub New(fName As String, lName As String, _bank As String, _sum As Integer)
        MyBase.New(fName, lName)
        Bank = _bank
        Me._sum = _sum
    End Sub

End Class

Вместо прежних значений теперь события будут в качестве параметров принимать объект, вызвавший событие, и объект AccountEventArgs, хранящий информацию о событии. Поскольку событие вызываем сам объект Client, то в качестве параметра sender мы передаем ключевое слово Me, указывающее на текущий объект. Теперь изменим основную программу:

Sub Main()

    Dim client1 As New Client("John", "Thompson", "City Bank", 200)

    AddHandler client1.Withdrowed, New Client.AccountStateHandler(AddressOf Color_Message)
    AddHandler client1.Added, AddressOf Show_Message

    client1.Withdraw(100)
    client1.Withdraw(150)
    client1.Put(150)

    Console.ReadLine()
End Sub

Private Sub Show_Message(sender As Object, e As AccountEventArgs)
    Console.WriteLine(e.message)
    Console.WriteLine("На счет добавлено {0} $", e.sum)
End Sub

Private Sub Color_Message(sender As Object, e As AccountEventArgs)
    'Устанавливаем красный цвет символов
    Console.ForegroundColor = ConsoleColor.Red
    Console.WriteLine("Была проведена попытка снять со счета {0} $", e.sum)
    Console.WriteLine(e.message)
    'Сбрасываем настройки цвета
    Console.ResetColor()
End Sub

Теперь если мы запустим программу. мы получим следующий вывод:

Была проведена попытка снять со счета 100 $
Деньги сняты со счета
Была проведена попытка снять со счета 150 $
Недостаточно денег на счете. Операция недействительна
Деньги добавлены на счет
На счет добавлено 150 $
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850