• Welcome to Valhalla Legends Archive.
 

[VB.NET] EventHandler, calling multiple

Started by Grok, November 14, 2007, 07:55 AM

Previous topic - Next topic

Grok

What are the restrictions on events?  In this sample, I am defining 3 events and calling them all one after another, but it seems only the first event fires each time.

Add Button1 and ListBox1 to a form.


Imports System
Imports System.Windows.Forms

Public Class Form1

    'class to carry the data for the raised event
    Public Class CustomEventArgs
        Inherits EventArgs
        Public id As Integer
        Public Sub New(ByVal id As Integer)
            Me.id = id
        End Sub
    End Class

    'delegate must be of the custom EventArgs class
    Public Delegate Sub CustomEventHandler(ByVal sender As Object, ByVal e As CustomEventArgs)

    'define some events
    Public Event Event1 As CustomEventHandler
    Public Event Event2 As CustomEventHandler
    Public Event Event3 As CustomEventHandler

    Public Sub ShowTheEventId(ByVal sender As Object, ByVal e As CustomEventArgs)
        ListBox1.Items.Add("event id = " + CStr(e.id))
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        AddHandler Me.Event1, AddressOf Me.ShowTheEventId
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim ea1 As CustomEventArgs = New CustomEventArgs(1)
        RaiseEvent Event1(Me, ea1)
        Dim ea2 As CustomEventArgs = New CustomEventArgs(2)
        RaiseEvent Event2(Me, ea2)
        Dim ea3 As CustomEventArgs = New CustomEventArgs(3)
        RaiseEvent Event3(Me, ea3)
    End Sub
End Class


Grok

Oops, found the problem.  I had only added handler for Event1.

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        AddHandler Me.Event1, AddressOf Me.ShowTheEventId
        AddHandler Me.Event2, AddressOf Me.ShowTheEventId
        AddHandler Me.Event3, AddressOf Me.ShowTheEventId
    End Sub


Works now.

MyndFyre

You should take a look into the defined pattern for raising events, what they use as "best practice."  I blogged about it - the blog is in C#, but it's essentially the same.  Part V in that blog talks about the pattern they suggest using.
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

Grok

I read your blog entry and the design pattern.  Seems to me my code is already correct.  What are you seeing?

Your part V sample wants to create a new Button class and override the predefined OnClick event.
My sample does not create any new derived class, and wants to define some new custom events to be called arbitrarily and carry a custom payload of data (id As Integer).

MyndFyre

You've got the delegate and event-args class right.  What they suggest is a protected virtual method:


Protected Overridable Sub OnEvent1(ByVal args As CustomEventArgs)
  If Not Event1 Is Nothing Then
    RaiseEvent Event1(Me, args)
  End If
End Sub


Encapsulating the event call in the OnXxx method prevents you from generating an exception if there aren't any event handlers registered for the event and still provides a clean and easy way to invoke it without worry.
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

Grok

#5
Quote from: MyndFyre[vL] on November 14, 2007, 10:53 PM
You've got the delegate and event-args class right.  What they suggest is a protected virtual method:


Protected Overridable Sub OnEvent1(ByVal args As CustomEventArgs)
  If Not Event1 Is Nothing Then
    RaiseEvent Event1(Me, args)
  End If
End Sub


Encapsulating the event call in the OnXxx method prevents you from generating an exception if there aren't any event handlers registered for the event and still provides a clean and easy way to invoke it without worry.

What is the scope of this encapsulated method?  Does it belong to the most specific class (Form) in which the events might be fired?
Also, the code as you have written it does not work in VB.NET 2005.  It is complaining that Event1 cannot be called directly(in the If conditional).

'Public Event Event1(sender As Object, e As CustomEventArgs)' is an event, and cannot be called directly. Use a 'RaiseEvent' statement to raise an event.

Complete code trying to implement your suggestion (contains errors):

Imports System
Imports System.Windows.Forms

Public Class Form1

    'class to carry the data for the raised event
    Public Class CustomEventArgs
        Inherits EventArgs
        Public id As Integer
        Public Sub New(ByVal id As Integer)
            Me.id = id
        End Sub
    End Class

    'delegate must be of the custom EventArgs class
    Public Delegate Sub CustomEventHandler(ByVal sender As Object, ByVal e As CustomEventArgs)

    'define some events
    Public Event Event1 As CustomEventHandler
    Public Event Event2 As CustomEventHandler
    Public Event Event3 As CustomEventHandler

    Protected Overridable Sub OnEvent1(ByVal args As CustomEventArgs)
        If Not Event1 Is Nothing Then
            RaiseEvent Event1(Me, args)
        End If
    End Sub

    Protected Overridable Sub OnEvent2(ByVal args As CustomEventArgs)
        If Not Event2 Is Nothing Then
            RaiseEvent Event2(Me, args)
        End If
    End Sub

    Protected Overridable Sub OnEvent3(ByVal args As CustomEventArgs)
        If Not Event3 Is Nothing Then
            RaiseEvent Event3(Me, args)
        End If
    End Sub

    Public Sub ShowTheEventId(ByVal sender As Object, ByVal e As CustomEventArgs)
        ListBox1.Items.Add("event id = " + CStr(e.id))
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        AddHandler Me.Event1, AddressOf Me.ShowTheEventId
        AddHandler Me.Event2, AddressOf Me.ShowTheEventId
        AddHandler Me.Event3, AddressOf Me.ShowTheEventId
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Me.OnEvent1(New CustomEventArgs(11))
        Me.OnEvent2(New CustomEventArgs(12))
        Me.OnEvent3(New CustomEventArgs(13))
    End Sub

End Class


Also, is the code in Button1_Click() the goal here?

Grok

Looks like I'll want to unregister each handler in some organized way, so I don't lose $2 million.