Link to home
Start Free TrialLog in
Avatar of PeterFrb
PeterFrbFlag for United States of America

asked on

VB.Net: Genericizing a RemoveHandler via a delegate to a subroutine

I've created a sample of the code that very well shows what I'm trying to do.  In my production code, I will have a subroutine in a class module that changes the value of a control via code, in which case, I do not want the firing of my event handler, which checks on the validity of an entry.  I'm not quite sure how to implement this, but I've set it up a test-case scenario below, in which I've experimented with the desired implementation.  My form has a single button and a checkbox; and in my test, the code changes the textbox value; and I do not want the firing of the event, which, in this case, will generate a pop-up message.

When using the code in the form shown below, my error is this:
__Test_AddressOf.Handler' cannot be converted to 'System.EventHandler'.

Open in new window


When I change it to "RemoveHandler chkTest.CheckedChanged, AddressOf UseHandler", then I get this error:
'AddressOf' operand must be the name of a method (without parentheses).

Open in new window


I'm guessing some experts out there have figured out how to solve this problem!  Thanks, in advance.  ~Peter Ferber


Public Class __Test_AddressOf
    Public Delegate Function TestDelegate(ByVal iFirst As Integer, ByVal iSecond As Integer) As Long
    Public Delegate Sub Handler(ByVal sender As System.Object, ByVal e As System.EventArgs)

    Private Sub MenuItemStartTests_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItemStartTests.Click
        Dim iFirst As Integer = 5
        Dim iSecond As Integer = 7
        MsgBox( _
            iFirst & "; " & iSecond & ": Multiplied = " & RunTest(5, 7, AddressOf Multiplier, AddressOf chkTest_CheckedChanged) & "; Added = " & RunTest(5, 7, AddressOf Adder, AddressOf chkTest_CheckedChanged))
    End Sub

    Private Function RunTest(ByVal iFirst As Integer, ByVal iSecond As Integer, ByVal testFunction As TestDelegate, ByVal UseHandler As Handler) As Long
        'Attempt to remove the handler before I change the checkbox.  Objective is not to see the message box "Logged Change!".
        RemoveHandler chkTest.CheckedChanged, UseHandler
        chkTest.Checked = (Not chkTest.Checked)

        RunTest = testFunction(iFirst, iSecond)
    End Function

    Private Function Multiplier(ByVal iFirst As Integer, ByVal iSecond As Integer) As Long
        Multiplier = iFirst * iSecond
    End Function

    Private Function Adder(ByVal iFirst As Integer, ByVal iSecond As Integer) As Long
        Adder = iFirst + iSecond
    End Function


    Private Sub chkTest_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkTest.CheckedChanged
        MsgBox("Logged Change!")
    End Sub
End Class

Open in new window

Avatar of Bob Learned
Bob Learned
Flag of United States of America image

I believe that you can pass the argument as EventHandler, not the delegate type.

http://social.msdn.microsoft.com/Forums/vstudio/en-US/09b141c8-6752-43e7-8555-8755e0a04a63/passing-addressof-as-a-parameter-to-a-subroutine

Option Strict On
Option Explicit On
Option Infer Off

Public Class Form1

  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim evHndlr As EventHandler
    evHndlr = AddressOf Button1_Click

    Call SomeMethod(evHndlr)

  End Sub

  Public Sub SomeMethod(ByVal evntHndlr As EventHandler)

    MessageBox.Show("Hi there!!")

  End Sub

End Class

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Ravi Vaddadi
Ravi Vaddadi
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of PeterFrb

ASKER

I tried your code, and there were a couple of issues with it, which I actually worked out.  Although my code recognized the word "Handler", the process would only work if I used "System.EventHandler"; and, in this case, I use the object, not the address of the object.  Not sure why your version did not work exactly on mine; but the exercise has been useful and fruitful, and I'll give you the credit on this question.  ~Peter


Public Class _Test_AddressOf_V2
    Public Delegate Function TestDelegate(ByVal iFirst As Integer, ByVal iSecond As Integer) As Long
    Public Delegate Sub Handler(ByVal sender As System.Object, ByVal e As System.EventArgs)

    Private Sub MenuItemStartTests_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItemStartTests_V3.Click
        Dim iFirst As Integer = 5
        Dim iSecond As Integer = 7
        MsgBox( _
            iFirst & "; " & iSecond & ": Multiplied = " & RunTest(5, 7, AddressOf Multiplier, AddressOf chkTest_CheckedChanged) & "; Added = " & RunTest(5, 7, AddressOf Adder, AddressOf chkTest_CheckedChanged))
    End Sub

    Private Function RunTest(ByVal iFirst As Integer, ByVal iSecond As Integer, ByVal testFunction As TestDelegate, ByVal UseHandler As System.EventHandler) As Long
        'Attempt to remove the handler before I change the checkbox.  Objective is not to see the message box "Logged Change!".
        RemoveHandler chkTest_V2.CheckedChanged, UseHandler
        chkTest_V2.Checked = (Not chkTest_V2.Checked)

        RunTest = testFunction(iFirst, iSecond)
    End Function

    Private Function Multiplier(ByVal iFirst As Integer, ByVal iSecond As Integer) As Long
        Multiplier = iFirst * iSecond
    End Function

    Private Function Adder(ByVal iFirst As Integer, ByVal iSecond As Integer) As Long
        Adder = iFirst + iSecond
    End Function


    Private Sub chkTest_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkTest_V2.CheckedChanged
        MsgBox("Logged Change!")
    End Sub

End Class

Open in new window

Not the exactly right answer for my setup; but that may be due to a reference quirk.  Am happy to have two working solutions, so that more people get good results from the question.  Many thanks, ~Peter