How to pass parameters in AddHandler using VB.NET - vb.net

This is what I'm trying to do. I'm creating a dynamic check with an autoback that when clicked, will go to my subroutine and do something. The two parameters I'm trying to pass is the table which the checkox is located and the name of the id of the checkbox. But I'm getting the error
AddressOf must be the name of a method without parentheses or
method does not have a signature compatible with sender as object, e system.eventArgs". Here is my code below.
chkSel = New CheckBox
chkSel.ID = "check_" & CStr(a)
chkSel.AutoPostBack = True
'This is where I get the error
AddHandler chkSel.CheckedChanged, AddressOf change_operating_items(tableName, "check_" & CStr(a))
tblcell.Controls.Add(chkSel)
tblrow.Cells.Add(tblcell)

You cannot pass arguments when you register an event handler.
Instead you can pass them when you raise that event in case of a custom event.
Here you need to handle the CheckedChanged event, cast the Sender to CheckBox and use it's ID property.
Sub change_operating_items(sender As Object, e As EventArgs)
Dim chk = DirectCast(sender, CheckBox)
Dim id = chk.ID
' do something with it '
EndSub

I had to use the following to send both the sender, e and the custom parameters:
AddHandler chart1.PostPaint, Sub(sender, e) Chart1_BottomPostPaintScorePlot(sender, e, GroupNames)
Private Sub Chart1_BottomPostPaintScorePlot(ByVal sender As Object, ByVal e As ChartPaintEventArgs, ByVal GroupNames() As String)
If TypeOf e.ChartElement Is Legend Then
'process the legend at the bottom
End If
End Sub

Related

I do not know why I am getting this 'Addressof' error?

I got a problem when using this add handler. It keeps on saying
"AddressOf operand must be the name of a method (without parentheses)".
I am not sure what I have done wrong for this to occur.
The code for the add handler:
AddHandler NudQuantityOfItem(a).SelectedItem, AddressOf TotalPrice(T)
The code for the Totalprice:
`Public Sub Totalprice(ByVal a As Integer)
For T = 1 To CInt(CustomerMenu.NudQuantityOfItem.SelectedItem)
TotalItemPriceCalculation(T, a)
Next
End Sub`
The code for the Quantity:
NudQuantityOfItem(a) = New numericupdowncounter
NudQuantityOfItem(a).Location = New Point(X, Y)
NudQuantityofitem(a).Width = 23 : cboQuantity(i).Height = 33`
I'm not positive of this but I think the target of teh AddressOf needs the same signature as hooked event.
e.g.
AddHandler c.TextChanged, AddressOf SetDirty
Private Sub SetDirty(ByVal sender As Object, ByVal e As System.EventArgs)
If Not mbDirty AndAlso Not mbFormLoad Then
mbDirty = True
....
End Sub
Note that SetDirty as the same parameters as does TextChanged.
In your case you would use Sender to defined the control that changed and then find the required value.

call combobox gotfocus event in inside the function

i am working on windows form application,i have two combo box.inside the function i have to check which combobox i have focuse.depend on that i have to do some operation
i have done coding in combox focus event like this
Private Sub cmbfrmwarehouse_GotFocus(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbfrmwarehouse.GotFocus
Dim currencombobox As ComboBox = sender
If currencombobox.Equals(cmbfrmwarehouse) Then
MessageBox.Show("it's in two")
ElseIf currencombobox.Equals(cmbTowarehouse) Then
MessageBox.Show("it's in three")
End If
End Sub
but i am not able to call this event in inside the function.how i can achieve this.Please help
They have to share the same event handler. The sender object is the combobox in question.
Private Sub cmbfrmwarehouse_GotFocus(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles cmbfrmwarehouse.GotFocus, cmbTowarehouse.GotFocus
Dim currencombobox As ComboBox = sender
If currencombobox.Equals(cmbfrmwarehouse) Then
MessageBox.Show("it's in two")
ElseIf currencombobox.Equals(cmbTowarehouse) Then
MessageBox.Show("it's in three")
End If
End Sub
You can't call an event. you can either raise the event (in this case, by setting the focus on the correct combo box) or call it's handler:
To raise this event use the Focus() method of the relevant combo box:
cmbfrmwarehouse.Focus() '' or cmbTowarehouse.Focus()
However, this will only execute the event handler for cmbfrmwarehouse unless you will also use OneFindeDay's answer and have both combo boxes share the same event handler for the GotFocus event.
The other way is to call the event handler simply call it like you would any other method:
cmbfrmwarehouse_GotFocus(cmbfrmwarehouse, EventArgs.Empty)
'' or
cmbfrmwarehouse_GotFocus(cmbTowarehouse, EventArgs.Empty)

Handling all textbox event in one Handler

I do know how to handle event of textboxes in my form. But want to make this code shorter because I will 30 textboxes. It's inefficient to use this:
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged, TextBox2.TextChanged, TextBox3.TextChanged, TextBox4.TextChanged, TextBox5.TextChanged, TextBox6.TextChanged, TextBox7.TextChanged, TextBox8.TextChanged, TextBox9.TextChanged, TextBox10.TextChanged
Dim tb As TextBox = CType(sender, TextBox)
Select Case tb.Name
Case "TextBox1"
MsgBox(tb.Text)
Case "TextBox2"
MsgBox(tb.Text)
End Select
End Sub
Is there a way to shorten the handler?
You can use Controls.OfType + AddHandler programmatically. For example:
Dim textBoxes = Me.Controls.OfType(Of TextBox)()
For Each txt In textBoxes
AddHandler txt.TextChanged, AddressOf txtTextChanged
Next
one handler for all:
Private Sub txtTextChanged(sender As Object, e As EventArgs)
Dim txt = DirectCast(sender, TextBox)
Select Case txt.Name
Case "TextBox1"
MsgBox(txt.Text)
Case "TextBox2"
MsgBox(txt.Text)
End Select
End Sub
If you have created very Textbox with the Designer, I don't think there is a better method.
But, if you have created the Textboxes dynamically, you should AddHandler in this way:
For i = 0 to 30
Dim TB as New Texbox
AddHandler TB.TextChanged, TextBox1_TextChanged
'Set every Property that you need
Me.Controls.Add(TB)
Next
Say If you are having that 30 textboxes inside a panel(PnlTextBoxes), Now you can create handler for your textboxes dynamically like this below
For each ctrl in PnlTextBoxes.controls
If TypeOf ctrl is TextBox then
AddHandler ctrl.TextChanged, AddressOf CommonClickHandler
end if
Next
Private Sub CommonHandler(ByVal sender As System.Object, _
ByVal e As System.EventArgs)
MsgBox(ctype(sender,TextBox).Text)
End Sub
The best way would be to inherit from TextBox, override its OnTextChanged method to add your custom handling code, and then use that on your form(s) instead of the built-in TextBox control.
That way, all of the event handling code is in one single place and you increase abstraction. The behavior follows and is defined within the control class itself, not the form that contains the control. And of course, it frees you from having a bunch of ugly, hard-to-maintain Handles statements, or worse, slow and even uglier For loops.
For example, add this code defining a new custom text box control to a new file in your project:
Public Class CustomTextBox : Inherits TextBox
Protected Overridable Sub OnTextChanged(e As EventArgs)
' Do whatever you want to do here...
MsgBox(Me.Text)
' Call the base class implementation for default behavior.
' (If you don't call this, the TextChanged event will never be raised!)
MyBase.OnTextChanged(e)
End Sub
End Class
Then, after you recompile, you should be able to replace your existing TextBox controls with the newly-defined CustomTextBox control that has all of your behavior built in.

Dynamic label with Handler

I have labels that are dynamically added on to the form with each of them having a link under their tag.
I also have the AddHandler lbTitle.Click to the dynamic labels, but when I try to do this, it doesn't work:
Private Sub lbTitle_Click(ByVal sender As Object, ByVal e As EventArgs)
Process.Start(e.Tag)
End Sub
Because
'tag' is not a member of 'System.EventArgs'
How can I solve this so that when someone clicks on of the dynamically added labels, it would launch the url from the label's tag.
To add an event handler, you need the AddressOf Operator
AddHandler lbTitle.Click, AddressOf lbTitle_Click
To get the reference to your Label in the event handler, you can use the sender argument:
Private Sub lbTitle_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim label = DirectCast(sender, Label)
Process.Start(label.Tag.ToString())
End Sub
The sender argument is the label, but you will need to cast it to the Label type before you can access its Tag property.
Process.Start(CType(sender, Label).Tag)
Or, to handle any type of control, you could cast it to the base Control type, instead:
Process.Start(CType(sender, Control).Tag)

how do I catch events on runtime objects

I'm creating a form with a few buttons and a combobox at runtime.
dim f as new form
(blah blah)
then the buttons acceptDescription and rejectDescription are set up...
then the combobox descriptionCombo is set up...
then...
AddHandler acceptDescription.Click, AddressOf handleAcceptedDescription
AddHandler rejectDescription.Click, AddressOf handleRejectedDescription
then I have these two methods to catch the click events... but can't figure out how to reference the other runtime generated controls. (combobox if accepted, form if rejected)
Private Sub handleAcceptedDescription(ByVal sender As System.Object, ByVal e As System.EventArgs)
'stub
'will need to reference the chosen combobox value here
dim acceptedDescription as string = descriptionCombo.selectedValue .tostring
End Sub
Private Sub handleRejectedDescription(ByVal sender As System.Object, ByVal e As System.EventArgs)
'I want to close the runtime created form here, but can't reference it
f.close()
'and return user to main form
Me.Focus()
End Sub
If the code for generating the form is in your main form, then declare the Form variable at the class level of the main form class so you can access it from the event handlers. Same goes for your combobox and text field- you need to make sure the variables are declared outside the scope of the handlers so you can reference them within the handlers.
Why can't you reference it? Just save it as a module/form-level variable and you're set.
In order to avoid global definitions, the best answer is
Private Sub handleRejectedDescription(ByVal sender As System.Object, ByVal e As System.EventArgs)
'sender is a button in this case.
'get the button
dim b as new button
b = ctype(sender,button)
'now get the button's parent form
dim f as new form
f = ctype(b.parent, form)
'now close the form
f.close()
End Sub