VB.NET AddHandler – Wire Events at Runtime (2026)

The VB.NET AddHandler statement connects events to methods at runtime instead of wiring them statically with the Handles keyword. This is essential when you create controls dynamically or need to assign event handlers based on conditions. This guide covers the syntax, the difference from Handles, dynamic controls, RemoveHandler, custom events, and common mistakes.

Need .NET help?

Building a desktop application?

I've been developing professionally in VB.NET and C# for over 17 years. From event handling to complete WinForms applications, I can help.

Handles vs. AddHandler

In WinForms there are two ways to connect an event to a method:

' Way 1: Handles clause (static, at design time)
Private Sub BtnSave_Click(sender As Object, e As EventArgs) Handles BtnSave.Click
    ' Automatically wired by the designer
End Sub

' Way 2: AddHandler (dynamic, at runtime)
AddHandler BtnSave.Click, AddressOf BtnSave_Click

Private Sub BtnSave_Click(sender As Object, e As EventArgs)
    ' No "Handles" needed
End Sub

The Handles clause only works with controls that exist at design time. AddHandler works anywhere, including controls you create through code. As soon as you generate controls dynamically, AddHandler is the only option.

AddHandler syntax

AddHandler Object.Event, AddressOf MethodName
  • Object.Event is the event you want to subscribe to (e.g. Button1.Click)
  • AddressOf returns a reference to the method that should be called
  • The method signature must match the event (e.g. sender As Object, e As EventArgs)

Basic example

A button click using AddHandler instead of Handles:

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        AddHandler BtnGreet.Click, AddressOf BtnGreet_Click
    End Sub

    Private Sub BtnGreet_Click(sender As Object, e As EventArgs)
        MessageBox.Show("Hello!")
    End Sub
End Class

Notice that BtnGreet_Click has no Handles clause at the end. The connection is made entirely through AddHandler in the Load event.

Creating dynamic controls

The most common use case for AddHandler: controls are created through code and need event handlers. Here is an example with dynamically created buttons:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim categories = New List(Of String) From {
        "Personal", "Business", "Archive"
    }

    For Each category In categories
        Dim btn As New Button()
        btn.Text = category
        btn.Size = New Size(120, 40)
        btn.Margin = New Padding(5)
        AddHandler btn.Click, AddressOf CategoryButton_Click
        FlowLayoutPanel1.Controls.Add(btn)
    Next
End Sub

Private Sub CategoryButton_Click(sender As Object, e As EventArgs)
    Dim btn = DirectCast(sender, Button)
    MessageBox.Show($"Category: {btn.Text}")
End Sub

Every button gets the same click handler. Use DirectCast(sender, Button) to determine which button was clicked. This scales to any number of controls without needing a separate handler for each one.

Complete example: numpad keyboard

A realistic example that creates a virtual numpad keyboard at runtime. Each key button is connected to a shared handler via AddHandler:

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim keys = New List(Of String) From {
            "7", "8", "9",
            "4", "5", "6",
            "1", "2", "3",
            "0", "00", ","
        }

        For Each key In keys
            Dim btn As New Button()
            btn.Text = key
            btn.Size = New Size(50, 50)
            btn.FlatStyle = FlatStyle.Flat
            btn.FlatAppearance.BorderSize = 1
            btn.BackColor = Color.White
            btn.Font = New Font("Segoe UI", 12, FontStyle.Bold)
            AddHandler btn.Click, AddressOf NumpadButton_Click
            FlowLayoutPanel1.Controls.Add(btn)
        Next
    End Sub

    Private Sub NumpadButton_Click(sender As Object, e As EventArgs)
        Dim btn = DirectCast(sender, Button)
        TextBox1.Text &= btn.Text
    End Sub
End Class

You only need a FlowLayoutPanel (about 180 x 260 pixels) and a TextBox on the form. The buttons are created entirely through code, no designer work needed.

Planning a project?

Need a polished WinForms application?

From event handling to complete data-driven desktop apps: I design software that lasts. Let's talk about your project.

RemoveHandler: disconnecting events

Use RemoveHandler to disconnect the event binding. This is important to avoid memory leaks when removing controls at runtime:

' Assign handler
AddHandler btn.Click, AddressOf Button_Click

' Remove handler
RemoveHandler btn.Click, AddressOf Button_Click

Use RemoveHandler whenever you:

  • Remove dynamic controls (e.g. when closing a tab)
  • Want to swap a handler (remove first, then add)
  • Want to prevent an event from firing multiple times

Multiple events, one handler

A single handler can process multiple events. This is especially useful for forms with many similar controls:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    AddHandler TxtName.TextChanged, AddressOf ValidateField
    AddHandler TxtEmail.TextChanged, AddressOf ValidateField
    AddHandler TxtPhone.TextChanged, AddressOf ValidateField
End Sub

Private Sub ValidateField(sender As Object, e As EventArgs)
    Dim txt = DirectCast(sender, TextBox)
    If String.IsNullOrWhiteSpace(txt.Text) Then
        txt.BackColor = Color.MistyRose
    Else
        txt.BackColor = Color.White
    End If
End Sub

All three text boxes share the ValidateField handler. The sender parameter identifies which text box changed.

Custom events with AddHandler

You can also define your own events and subscribe to them with AddHandler. This is useful for loosely coupled communication between classes:

Public Class FileWatcher
    Public Event FileChanged(filePath As String)

    Public Sub CheckForChanges()
        ' Check logic...
        RaiseEvent FileChanged("C:\data\config.xml")
    End Sub
End Class

' In the form:
Private WithEvents watcher As New FileWatcher()

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    AddHandler watcher.FileChanged, AddressOf OnFileChanged
End Sub

Private Sub OnFileChanged(filePath As String)
    MessageBox.Show($"File changed: {filePath}")
End Sub

The class uses RaiseEvent to trigger the event. The subscriber reacts through AddHandler. This keeps the FileWatcher class independent from the form.

Common mistakes

Handler registered multiple times

' BAD - each click adds another handler
Private Sub BtnRefresh_Click(sender As Object, e As EventArgs) Handles BtnRefresh.Click
    AddHandler Timer1.Tick, AddressOf Timer1_Tick
End Sub

' GOOD - register handler once in Load
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    AddHandler Timer1.Tick, AddressOf Timer1_Tick
End Sub

Calling AddHandler multiple times for the same event and method causes the method to execute multiple times. Register handlers in Load or call RemoveHandler first. For more on timers, see the VB.NET Timer guide.

Wrong method signature

' BAD - parameters don't match the event
Private Sub Button_Click(text As String)
End Sub

' GOOD - signature matches the Click event
Private Sub Button_Click(sender As Object, e As EventArgs)
End Sub

The method must have exactly the parameter types the event expects. For Click, that is (sender As Object, e As EventArgs). The compiler will report an error if the signature does not match.

Forgetting RemoveHandler for dynamic controls

If you remove controls with Controls.Remove() but don’t disconnect the handler, the reference keeps the object in memory. Always call RemoveHandler before removing a dynamic control.

Need expert support?

Looking for an experienced .NET developer?

I'll take on your project, from event handling to finished desktop applications. Just drop me a message.

FAQ

What is the difference between Handles and AddHandler?

Handles connects an event to a method statically at design time. AddHandler connects an event dynamically at runtime. For controls created through code, AddHandler is the only option.

Can I call AddHandler multiple times for the same event?

Yes, but the handler will execute multiple times. If that is not what you want, call RemoveHandler first or register the handler only once in the Load event.

When do I need RemoveHandler?

Whenever you remove dynamic controls, want to swap handlers, or need to prevent an event from firing multiple times. Without RemoveHandler you risk memory leaks.

Can one handler process multiple events?

Yes. Use AddHandler multiple times with different controls but the same method. The sender parameter tells you which control triggered the event.

What does AddressOf mean in VB.NET?

AddressOf creates a delegate, which is a typed reference to a method. It is used with AddHandler to tell the event which method to call when the event is raised.

Wrapping up

The AddHandler statement makes event handling in VB.NET flexible. Use it for dynamically created controls, when you need to assign or swap handlers at runtime, and for custom events in your classes. Remember to call RemoveHandler when removing controls, and register handlers only once to avoid multiple executions. For related topics, check out the VB.NET Timer guide and the VB.NET List guide.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Robert Skibbe
Datenschutz-Übersicht

Diese Website verwendet Cookies, damit wir dir die bestmögliche Benutzererfahrung bieten können. Cookie-Informationen werden in deinem Browser gespeichert und führen Funktionen aus, wie das Wiedererkennen von dir, wenn du auf unsere Website zurückkehrst, und hilft unserem Team zu verstehen, welche Abschnitte der Website für dich am interessantesten und nützlichsten sind.