natli
natli

Reputation: 3822

AddressOf with parameter

One way or another I need to link groupID (and one other integer) to the button I am dynamically adding.. any ideas?

What I can do;

AddHandler mybutton.Click, AddressOf PrintMessage

Private Sub PrintMessage(ByVal sender As System.Object, ByVal e As System.EventArgs)
    MessageBox.Show("Dynamic event happened!")
End Sub

What I can't do, but want to;

AddHandler mybutton.Click, AddressOf PrintMessage(groupID)

Private Sub PrintMessage(ByVal groupID as Integer)
    MessageBox.Show("Dynamic event happened!" & groupID .tostring)
End Sub

Upvotes: 17

Views: 50719

Answers (8)

Damian K.
Damian K.

Reputation: 333

No problem ;-)

For example:

Private ComboActionsOnValueChanged As New Dictionary(Of ComboBox, EventHandler)

'somewhere in function
dim del = Sub(theSender, eventArgs)
           MsgBox(CType(theSender, ComboBox).Name & " test")
          End Sub
ComboActionsOnValueChanged.Add(myCombo, del)

'somewhere else
Dim delTest = ComboActionsOnValueChanged(myCombo)
RemoveHandler myCombo.SelectedValueChanged, delTest
myCombo.DataSource = someDataSource
AddHandler myCombo.SelectedValueChanged, delTest

as we expect, event won't fire after DataSource change in this place

Upvotes: 0

Josip Sibenik
Josip Sibenik

Reputation: 21

My solution:

AddHandler menuItemYear.Items(i).MouseUp, Sub() menu_year(2019)

Private Sub menu_year(ByVal intYear As Integer)
   'do something
End Sub

Upvotes: 1

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112392

You can create your own button class and add anything you want to it

Public Class MyButton
    Inherits Button

    Private _groupID As Integer
    Public Property GroupID() As Integer
        Get
            Return _groupID
        End Get
        Set(ByVal value As Integer)
            _groupID = value
        End Set
    End Property

    Private _anotherInteger As Integer
    Public Property AnotherInteger() As Integer
        Get
            Return _anotherInteger
        End Get
        Set(ByVal value As Integer)
            _anotherInteger = value
        End Set
    End Property

End Class

Since VB 2010 you can simply write

Public Class MyButton
    Inherits Button

    Public Property GroupID As Integer

    Public Property AnotherInteger As Integer
End Class

You can access the button by casting the sender

Private Sub PrintMessage(ByVal sender As Object, ByVal e As EventArgs)
    Dim btn = DirectCast(sender, MyButton)
    MessageBox.Show( _
      String.Format("GroupID = {0}, AnotherInteger = {1}", _
                    btn.GroupID, btn.AnotherInteger))
End Sub

These new properties can even be set in the properties window (under Misc).

The controls defined in the current project automatically appear in the toolbox.

Upvotes: 5

Dinesh Halpage
Dinesh Halpage

Reputation: 109

The below worked for me:

Dim bStart = New Button With {.Text = "START"}
AddHandler bStart.Click, Function(sender, e) TriggerProcess(any Long value)


Private Function TriggerProcess(ByVal paramName As Long) As Boolean
 ' any processing logic
 Return True
End Function

Upvotes: 2

Triet Nguyen
Triet Nguyen

Reputation: 821

You can use delegate which very clear for your code follow as:

Define a delegate

Public Delegate Sub ControlClickDelegate(ByVal sender As Object, ByVal e As EventArgs)

Custom button class

Public Class CustomButton
    Inherits System.Windows.Forms.Button
#Region "property delegate"

    Private controlClickDelegate As ControlClickDelegate

    Public Property ClickHandlerDelegate As ControlClickDelegate
        Get
            Return controlClickDelegate
        End Get
        Set(ByVal Value As ControlClickDelegate)
            controlClickDelegate = Value
        End Set
    End Property

#End Region

    Public Sub RegisterEventHandler()
        AddHandler Me.Click, AddressOf OnClicking
    End Sub

    Private Sub OnClicking(ByVal sender As Object, e As System.EventArgs)
        If (Me.controlClickDelegate IsNot Nothing) Then
            Me.controlClickDelegate(sender, e)
        End If
    End Sub

End Class

MainForm

Public Class MainForm
    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.

        Me.CusButton1.ClickHandlerDelegate = AddressOf Me.btnClick
        Me.CusButton1.RegisterEventHandler()
    End Sub

    Private Sub btnClick(ByVal sender As Object, ByVal e As EventArgs)
        Me.TextBox1.Text = "Hello world"
        End Sub

End Class

Upvotes: 2

Mehrdad Ordoukhani
Mehrdad Ordoukhani

Reputation: 11

There are few ways to do that depending of the complexity and number of parameters required. 1. Use Tag for adding a complex structure 2. Inherit the the Button class and add the values as class members then populate them before using it. That gives you a lot more flexibility.

If you are using web version 3. You cannot add it to Tag, but for simple values assign it to index use .Attributes.Add("name"). This gets added to the HTML tags and not the Server side. You can then use the index to access a server side structure for complex systems. 4. Use sessions to store values and store the session reference to Name attribute as described above (#3).

Upvotes: 0

JaredPar
JaredPar

Reputation: 754763

There is no way to do this with AddressOf itself. What you're looking for is a lambda expression.

AddHandler myButton.Click, Function(sender, e) PrintMessage(groupId)

Private Sub PrintMessage(ByVal groupID as Integer)
    MessageBox.Show("Dynamic event happened!" & groupID .tostring)
End Sub

Upvotes: 48

haiyyu
haiyyu

Reputation: 2242

Use the Tag property of the button.

Button1.Tag = someObject

AddressOf gets the address of a method, and thus you cannot pass parameters to it.

Upvotes: 2

Related Questions