How to remove an event handler or handle?

UncleRonin

Well-known member
Joined
Feb 28, 2006
Messages
230
Location
South Africa
Programming Experience
5-10
Okay, I know about using RemoveHandler which isn't a problem... What I really want to know is if there are other ways to remove handlers/handles?

I have a bunch of controls which are code generated and added to a form. I then perform some operation and if it fails I must then get rid of these controls and their associated handles. Can I use .Dispose() on the control and then this will automatically release any handles it may have or must I specifically use RemoveHandler?

I can get around this by reorganising my code so that handles are only added if the operation is successful but then I have to reiterate through all the controls which wastes time and I don't want that.

This isn't a major thing or anything but I'm really curious!
 
RemoveHandler is a method to stop receiving events when it is called for and is not required otherwise. For comparison, AddHandler does the same as a Handles clause and these two methods to start receiving events can be used interchangably. You never see people that uses Handles do a RemoveHandler before removing/disposing the instances, do you?
 
Actually, the Handles clause and the AddHandler statement aren't quite the same. The Handles clause applies to a variable, while the AddHandler statement applies to an object. Try this code out for size:
VB.NET:
Public Class Form1

    Private WithEvents button1 As Button
    Private button2 As Button

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.button1 = New Button
        Me.button2 = New Button

        Me.button1.Name = "First button1"
        Me.button2.Name = "First button2"

        AddHandler button2.Click, AddressOf Button_Click

        Me.button1.PerformClick()
        Me.button2.PerformClick()

        Me.button1 = New Button
        Me.button2 = New Button

        Me.button1.Name = "Second button1"
        Me.button2.Name = "Second button2"

        Me.button1.PerformClick()
        Me.button2.PerformClick()
    End Sub

    Private Sub Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles button1.Click
        Dim btn As Button = DirectCast(sender, Button)

        MessageBox.Show(btn.Name & " was clicked.")
    End Sub

End Class
You'll see that there are only three messages displayed. That's because the Handles clause applies to the variable, so whatever object that variable refers to is what has its event handled by that method. The AddHandler on the other hand applies to the specific object that was referred to at the time that the AddHandler statement was executed, so there is never an event handler for the fourth Button attached.

As for the initial question, if the controls are no longer on the form then they aren't going to be raising any events, so there's no reason to use RemoveHandler at all. You would only use RemoveHandler if you wanted a specific method to stop handling the specified event. If there will be no instances of that event raised then it serves no useful purpose. It would be like taking the wheels off a car that had no engine to make sure noone drives it.
 
Haha nice analogy at the end :) I just wanted to check and be sure. If a method is handling the events for some controls and the controls are disposed, will there not be some memory wasted since the method is still 'handling' the events (which will never occur)?

And another question: If a groupbox has controls on it and it gets disposed, will these controls get disposed properly as well?
 
Here's part of the implementation of Control.Dispose:
VB.NET:
                  [COLOR=#1000a0]Dim[/COLOR] [B]collection1[/B] [COLOR=#1000a0]As[/COLOR] [URL="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=45"]ControlCollection[/URL] = [COLOR=#1000a0]DirectCast[/COLOR]([COLOR=#1000a0]Me[/COLOR].[URL="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=46"]Properties[/URL].[URL="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=47"]GetObject[/URL]([URL="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=48"]Control[/URL].[URL="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=49"]PropControlsCollection[/URL]), [URL="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=50"]ControlCollection[/URL])
                   [COLOR=#1000a0]If[/COLOR] ([COLOR=#1000a0]Not[/COLOR] [URL="http://www.vbdotnetforums.com/"]collection1[/URL] [COLOR=#1000a0]Is[/COLOR] [COLOR=#800000]Nothing[/COLOR]) [COLOR=#1000a0]Then[/COLOR]
                         [COLOR=#1000a0]Dim[/COLOR] [B]num1[/B] [COLOR=#1000a0]As[/COLOR] [URL="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=51"]Integer[/URL] = [COLOR=#800000]0
[/COLOR]                         [COLOR=#1000a0]Do While[/COLOR] ([URL="http://www.vbdotnetforums.com/"]num1[/URL] < [URL="http://www.vbdotnetforums.com/"]collection1[/URL].[URL="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=52"]Count[/URL])
                               [COLOR=#1000a0]Dim[/COLOR] [B]control1[/B] [COLOR=#1000a0]As[/COLOR] [URL="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=53"]Control[/URL] = [URL="http://www.vbdotnetforums.com/"]collection1[/URL].[URL="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=54"]Item[/URL]([URL="http://www.vbdotnetforums.com/"]num1[/URL])
                               [URL="http://www.vbdotnetforums.com/"]control1[/URL].[URL="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=55"]parent[/URL] = [COLOR=#800000]Nothing[/COLOR]
                               [URL="http://www.vbdotnetforums.com/"]control1[/URL].[URL="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=56"]Dispose[/URL]
                               [URL="http://www.vbdotnetforums.com/"]num1[/URL] += [COLOR=#800000]1[/COLOR]
                         [COLOR=#1000a0]Loop[/COLOR]
                         [COLOR=#1000a0]Me[/COLOR].[URL="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=57"]Properties[/URL].[URL="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=58"]SetObject[/URL]([URL="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=59"]Control[/URL].[URL="http://www.aisto.com/roeder/dotnet/Default.aspx?Object=60"]PropControlsCollection[/URL], [COLOR=#800000]Nothing[/COLOR])
                   [COLOR=#1000a0]End If[/COLOR]
This section disposes every child control, so the answer to your question is Yes.
 
Back
Top