AddHandler

From Xojo Documentation

Language Keyword

Directs the handling of an event to a delegate method.

Usage

AddHandler eventName, delegateMethod

Part Description
eventName The name of the event that you are handling.
delegateMethod The name of the method that will be used to handle the event.

Notes

Generally you will create a subclass to expose event handlers for you to implement. AddHandler is provides a way for you to instantiate a class in code and still have access to its event handlers. The delegateMethod method declaration must consist of:

  • A reference to the object being handled. This is the sender object and it must be the first parameter in the delegate and must be the correct type. You can get this reference using AddressOf or WeakAddressOf.
  • The same parameters of the event you are handling should follow next in the same order with the same types. The parameter names can be changed.
  • If the event you are handling returns a value, then the delegate method must also return the same value type.

A handler can handle any number of events, but an event can only have one event handler. To change the event handler for an event after you have added one, you must first remove the existing handler with RemoveHandler. You can then add the new handler.

fa-info-circle-32.png
AddHandler is a keyword, not a function so do not surround the parameters with parentheses.

Exceptions

Exception Description
RuntimeException If you implement an event handler that is already implemented without first removing it using RemoveHandler.

Sample Code

This example show you how you can handle the Timer.Run event in your own method so that you do not have to create a Timer subclass.

Start by adding a property for the Timer to the layout:

MyTimer As Timer

Now add a ProgressBar to the layout. The Timer will update the ProgressBar. In the Open event handler of the layout, instantiate the Timer and indicate that its Action event handler should be handled by a method (called TimerRun -- you'll create the method a moment):

MyTimer = New Timer
MyTimer.Period = 1000
MyTimer.RunMode = Timer.RunModes.Multiple
AddHandler MyTimer.Action, AddressOf TimerRun

Now add the TimerRun method to the layout:

Sub TimerRun(sender As Timer)
// This code works on Desktop and uses ProgressBar.
If ProgressBar1.Value < ProgressBar1.MaximumValue Then
ProgressBar1.Value = ProgressBar1.Value + 1
Else
// Stop Timer and Remove the handler
sender.RunMode = Timer.RunModes.Off
RemoveHandler MyTimer.Action, AddressOf TimerRun
End If
End Sub

Now run the project and watch the Timer updated the ProgressBar.

iOS Projects

This example lets you handle the Timer.Action event without creating a Timer subclass. Start by adding a property to the layout:

MyTimer As Xojo.Core.Timer

Next, add an iOSProgressBar to the layout. The Timer will update the ProgressBar. In the Open event handler of the layout, instantiate the Timer and indicate that its Action event handler should be handled by a method, TimerAction, that you will add to the layout:

MyTimer = New Xojo.Core.Timer
MyTimer.Period = 1000
MyTimer.Mode = Xojo.Core.Timer.Modes.Multiple

AddHandler MyTimer.Action, AddressOf TimerAction

Now add the TimerAction method to the layout:

Sub TimerAction(sender As Xojo.Core.Timer)
// This code works on iOS and uses iOSProgressBar.
// Change the properties as appropriate for desktop apps.
If ProgressBar1.CurrentValue < ProgressBar1.MaxValue Then
ProgressBar1.CurrentValue = ProgressBar1.CurrentValue + 1
Else
// Stop Timer and Remove the handler
sender.Mode = Xojo.Core.Timer.Modes.Off
RemoveHandler MyTimer.Action, AddressOf TimerAction
End If
End Sub

Remember that the first parameter to TimerAction must be of the type of the original object, in this case a Timer. When you run the project, the ProgressBar is updated once per second. When using AddHandler on a class, it is more productive to use WeakAddressOf to ensure that you do not inadvertently retain references. To do so, use WeakAddressOf in place of AddressOf in the code:

MyTimer = New Xojo.Core.Timer
MyTimer.Period = 1000
MyTimer.Mode = Xojo.Core.Timer.Modes.Multiple

AddHandler MyTimer.Action, WeakAddressOf TimerAction

And here:

Sub TimerAction(sender As Xojo.Core.Timer)
// This code works on iOS and uses iOSProgressBar.
// Change the properties as appropriate for desktop apps.
If ProgressBar1.CurrentValue < ProgressBar1.MaxValue Then
ProgressBar1.CurrentValue = ProgressBar1.CurrentValue + 1
Else
// Stop Timer and Remove the handler
sender.Mode = Xojo.Core.Timer.Modes.Off
RemoveHandler MyTimer.Action, WeakAddressOf TimerAction
End If
End Sub

See Also

RemoveHandler statement