Multiple event handlers for the same event in VB.NET
Asked Answered
P

3

6

I've written two event handlers for the TextBox.Leave event for a TextBox1

The reason for this is that the first handler is a common one for multiple TextBox.Leave events which validates the values, and the second one is specific for the above TextBox1 which does some calculation of values.

My query is that can I know which of the two handlers will execute first when TextBox1.Leave happens?

(I know I can remove the code from the common handler to the specific one for TextBox1, but still I wish to know if there is a way.)

Thanks

Pr answered 25/9, 2012 at 17:46 Comment(0)
H
13

As long as the event handlers are added using the AddHandler statement, the event handlers are guaranteed to be called in the same order that they were added. If, on the other hand, you are using the Handles modifier on the event handler methods, I don't think there is any way to be sure what the order will be.

Here's a simple example that demonstrates the order as determined by the order in which AddHandler is called:

Public Class FormVb1
    Public Class Test
        Public Event TestEvent()

        Public Sub RaiseTest()
            RaiseEvent TestEvent()
        End Sub
    End Class

    Private _myTest As New Test()

    Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
        AddHandler _myTest.TestEvent, AddressOf Handler1
        AddHandler _myTest.TestEvent, AddressOf Handler2
        _myTest.RaiseTest()
        RemoveHandler _myTest.TestEvent, AddressOf Handler1
        RemoveHandler _myTest.TestEvent, AddressOf Handler2
    End Sub

    Private Sub Handler1()
        MessageBox.Show("Called first")
    End Sub

    Private Sub Handler2()
        MessageBox.Show("Called second")
    End Sub
End Class
Hayleyhayloft answered 25/9, 2012 at 17:49 Comment(3)
thanks :) But mustn't be there an order though using 'Handles' ? I mean it can't and shouldn't be random, lets say, for a case of 3 handlers for an event?Pr
I'm sure it's not entirely random. The order would be determined by the compiler, so once the assembly is compiled, it should always stay the same, but I don't know whether or not the compiler guarantees that the order will be the same every time it builds. I also don't know if every version of the compiler uses the same order. I'd say, if order matters, use the AddHandler statement to set the order explicitly in the code. If nothing else, it will be more obvious that it was intended later on.Hayleyhayloft
Steven is almost certainly correct in that the ordering stays fixed. On execution these handlers will be generated internally using all of the same machinery that the AddHandler method uses, but whether it sequences by alphabetical order, hash code order, source code order etc. would be a question for the Visual Studio developers. The answer should still only be used to satisfy curiosity though as relying on it would be a mistake, it could change without warning.Wakeen
H
4

I'd recommend you change to having a single handler, and detect which textbox is being left:

Private Sub txt_Leave(sender As Object, e As System.EventArgs) Handles TextBox1.Leave, TextBox2.Leave
  Dim txt As TextBox = DirectCast(sender, TextBox)
  If txt Is TextBox1 Then
    txt.Text = "Very important textbox!"
  Else
    txt.Text = "Boring textbox ho hum."
  End If
End Sub
Hooves answered 26/9, 2012 at 2:30 Comment(1)
Is it necessary to use AddHandler ? Or can I just add Handles after txt_Leave(...) definition ?Pr
K
0

This is just additional information not related to the order of execution of multiple event handlers with the same "Handles" clause. It may be of interest, though, to those wondering about when to use a "Handles" clause and when to use the "AddHandler" statement.

Addhandler is more useful when using a UDC (User Defined Control) to execute procedures/functions or manipulate data within a form.

UDCs know nothing about the form on which they have been attached or referenced.

They are generic and written for reuse in many projects.

Take (for example) the standard "TextBox" control. Does TextBox know anything about the form on which it rests? No. All its properties are available to the form but none of the form's properties is available to the Textbox. (The Textbox is a pre-supplied "UDC", and Microsoft is the User defining it)

If you want your own UDC to operate on data in the main form, you define a public event within the UDC (let's call this event "UC_Update") It is placed on a single line at the top of the code in the UDC:

 Public Event UC_Update      ' UC stands for "User Control"

When your UDC (let's call it "MyControl") wants to work with data on its parent form, it can call this event (within the UDC code) with the line:

 RaiseEvent UC_Update

Within the code of the form on which this control has been placed or referenced, you attach this event belonging to your UDC to an instance of your control and "point" that event to another routine written in the form. To do this, you use the "AddHandler" directive and an associated "AddressOf" operator.

Say the process you have written to manipulate data/controls in the form along with data/methods in your UDC, is called "MyControlUpdater". It will be in your form and look like this:

 Private Sub MyControlsUpdater()
 ......(code).......
 end sub  

The "(code)" may be lines that use data in your UDC (via public properties or public Subs/Functions) or use data or controls within your form. Your UDC can now do something with items on your form.``

You would place within your form's code the following:

 AddHandler MyControl.UC_Update, AddressOf MyControlsUpdater

This directive is placed somewhere after the UDC has been instantiated:

 Dim oMyControl as New MyControl
 AddHandler oMyControl.UC_Update, AddressOf MyControlsUpdater

If, however, the UDC is physically on your form as "MyControl1", placed there via the Visual Studio Toolbox, then you would add the Handler in your form's "Load" procedure:

 Private Sub Form1_Load(sender as object, e as eventargs) Handles Me.Load
 AddHandler MyControl1.UC_Update, AddressOf MyControlsUpdater 

It is important to note that you cannot pass parameters via this process (when using "AddressOf"). That is why there is no "sender" in the "MyControlsUpdater" subroutine. Values that relate to your UDC must be obtained by way of public properties in that UDC. Public UDC functions and subroutines (subs) are also available.

If you are NOT working with a UDC (often the case) but with controls created by others such as Microsoft (and therefore the internal code of the control is not available), then you use the "Handles" clause to establish how the control is handled when a certain event arises (such as a "Click" on the control).

 Private sub UpdateData(sender as object, e as eventargs) handles Textbox1.Click
 ........(code)......
 End Sub

Of course, if your own UDC doesn't need to know anything about data on your form and you are referencing it rather than adding it physically to the form, you can just use the "Handles" delegation on your own UDC as per normal:

 Dim MyControl1 as New MyControl 

 Private Sub UpdataData(sender as object, e as eventargs) _
                        handles MyControl1.Text.Leave

Here the form uses data in the control (via public properties) rather than the control using data within the form.

Kwashiorkor answered 2/8, 2022 at 16:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.