Creating Runtime Event Handlers
You can define multiple responses to a single event. Like a symphony conductor orchestrating several musicians playing simultaneously , you can have a single event invoke multiple, orchestrated event handlers.
If you define more than one procedure with the same Handles clause, each procedure is called for a single event. For example, two separate procedures with Handles MyBase. Click clauses will each be invoked when the Click event occurs. This is related to the subject of multicast delegates (see Chapter 9). Suppose you have the Form1_Click event handler defined in Listing 8.8. If you defined a second procedure, arbitrarily named Form1_ClickToo with the Handles MyBase.Click clause, when Form1 was clicked, both procedures would be called. This works because delegates store a list of procedure addresses and invoke every procedure in the list when the event occurs.
You can also change the behavior of an event or layer behaviors at runtime with the AddHandler and RemoveHandler methods , which have the following syntax:
AddHandler object.event, AddressOf object.eventhandler RemoveHandler object.event, AddressOf object.eventhandler
object.event is the instance and event type whose invocation list we want to modify. object.eventhandler is the object and event procedure that we want to add to or remove from the invocation list. The second argument of AddHandler and RemoveHandler is a delegate. Recall that AddressOf returns a delegate, satisfying the second argument requirement.
A common situation in which you need to manage event handlers dynamically is when you are dynamically creating and removing things, namely controls, that use event handlers. Listing 8.9 demonstrates code that adds buttons to a form at runtime. A button would be of little use without a Click handler, so the code demonstrates using AddHandler to define a response for the button. The code in Listing 8.9 displays the name of the button that invoked the Click event.
Listing 8.9 Adding button controls and adding Click event handlers at runtime.
1: Private Sub ButtonClick(ByVal Sender As System.Object, _ 2: ByVal e As System.EventArgs) 3: 4: MsgBox(CType(Sender, Button).Text) 5: End Sub 6: 7: Private Sub button1_Click(ByVal sender As System.Object, _ 8: ByVal e As System.EventArgs) Handles button1.Click 9: 10: Dim Button As New Button() 11: Controls().Add(Button) 12: Button.Text = "Button" & Controls().Count 13: Button.Top = Controls().Count * Button.Height 14: AddHandler Button.Click, AddressOf ButtonClick 15: End Sub
The Windows application project contains a single button, button1. When button1 is clicked, it creates a new instance of a button control. The button control is added to the ControlCollection, Controls; Controls is a member of the Form class. The button text is "button" with the number of controls appended to the text to create a unique caption. Line 13 positions the button to ensure it's not covered by other buttons, and line 14 adds the handler ButtonClick to the button's Click event invocation list. When the button is clicked, lines 1 through 5 are executed.
You might use a technique similar to the one in Listing 8.9 if you are adding menu items, toolbar buttons, or creating forms or controls at runtime. Refer to Chapter 15, "Using Windows Forms," for more on dynamic control creation.