When you are building an application using VB, you will most certainly need to hook into various event sources. While events are very common when you are constructing a GUI application (WPF, ASP.NET, Windows Forms), they are also very important for non-UI tasks such as working with threads, callbacks from database operations, and other tasks.
As it turns out, VB has a few "oddities" regarding how to hook into a given event, so I wanted to do a quick blog post which will hopefully clarify our choices.
First of all, when you are declaring a field of a Class, Structure or Module, you have the option of making use of the WithEvents keyword. When you do so, you are able to selectively hook into events of interest using the Handles clause on a given class method. One part of this puzzle which is hidden from view is the fact that each and every .NET event is defined in termes of a related delegate. As you may know, the .NET delegate type allows us to capture, in a strongly typed manner, the address of another method. Given this point, the method that uses the Handles clause must match the underlying delegate definition, or you will receive compile time errors!
Here is a simple example of capturing the Click event of the Windows Forms Button class. Take note that the method receiving the event notification takes an Object as the first parameter, and a EventArgs as the second, given that the Click event has been defined in terms of a system delegate named System.EventHandler.
Class MainWindow
Inherits Form
' Inform the Button we are interested in listening to
' events.
Private WithEvents btnClickMe As Button
Public Sub New()
btnClickMe = New Button With {.Height = 100,
.Width = 100, .Text = "OK!"}
Me.Controls.Add(btnClickMe)
End Sub
Private Sub btnClickMe_Click(ByVal sender As Object,
ByVal e As System.EventArgs) Handles btnClickMe.Click
MessageBox.Show("Clicked!")
End Sub
End Class
Now, one gotchya is that the WithEvents keyword can only be used for fields (local variables need not apply). When you wish to handle an event for a local variable, you are required to use the AddHandler statement. Here, you will specify the event name and method to call (via the AddressOf operator). However, in this case the Handles clause is not used. Here is a re-working of the previous class which illustrates these points:
Class MainWindow
Inherits Form
Public Sub New()
Dim btnClickMe As Button
btnClickMe = New Button With {.Height = 100,
.Width = 100, .Text = "OK!"}
AddHandler btnClickMe.Click, AddressOf btnClickMe_Click
Me.Controls.Add(btnClickMe)
End Sub
...
End Class
Of course, with the release of .NET 4.0, VB has full support for lambda expressions. This is yet another way to hook into event sources, which was covered in a previous blog post.
2b8d2e31-e85e-443b-bebd-5d6330036cde|1|5.0