it seems that adding for example a button Dim myButton as New Button and then addHandler to mySub("lol", 255) is not possible.
Where mySub is Shared Sub MySub(byRef myString as string, myInteger as Integer)
So: addHandler myButton.click, addressOf mySub("lol", 255) - returns an error saying it does not work with parentheses or whatever.
I somehow see why this might not be possible, so I'm looking for a work-around on this problem.
Please help _jakeCake
First of all the syntax for AddHandler would be:
AddHandler myButton.click, AddressOf mySub
Secondly the signature of the eventhandler procedure must match the signature of the event like so:
Private Sub myButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
[...]
End Sub
Maybe you could look into using a lambda expression when you add the event. When using lambda's in VB.NET the function must return a value and does not support multi-line statements.
Dim myButton As New Button
AddHandler myButton.Click, Function(senderObj, args) myFunc("lol", 255)
Related
I had difficulty deleting an event
, I only call contextmenu temporarily (assigning the event and after the event has finished I no longer use it), and so on for each call.
sub register()
Dim f_Cm As Windows.Forms.ContextMenuStrip = New System.Windows.Forms.ContextMenuStrip(Me.components)
AddHandler f_Cm.Closed, Sub() f_Cm_Closed(f_Cm)
end sub
'mycode1
Private Sub f_Cm_Closed(f_Cm As Windows.Forms.ContextMenuStrip)
'....mycode
RemoveHandler f_Cm.Closed, Sub() f_Cm_Closed(f_Cm)
End Sub
'mycode2
Private Sub f_Cm_Closed(f_Cm As Windows.Forms.ContextMenuStrip)
'....mycode
Dim e1 As ToolStripDropDownClosedEventArgs = address of f_Cm_Closed(f_Cm)
RemoveHandler f_Cm.Closed, e1
End Sub
Do I need to delete them in this case? and how to do this?
Thanks you!
Sub() f_Cm_Closed(f_Cm) is what's called a lambda expression. Lambda expression are basically methods without a name; they're useful shortcuts in some situations. What you are doing in the code Sub() f_Cm_Closed(f_Cm) is creating a new, nameless method, which then calls f_Cm_Closed(f_Cm).
This isn't what you want, you want to pass a reference directly to your handler so you can remove it later. For that, you use AddressOf.
Before you can do that, the method signatures will have to match. So
Private Sub f_Cm_Closed(f_Cm As Windows.Forms.ContextMenuStrip)
will have to become
Private Sub f_Cm_Closed(sender As Object, e As ToolStripDropDownClosedEventArgs)
sender will always be f_Cm, so you can cast like so:
Dim f_Cm As Windows.Forms.ContextMenuStrip = sender
To pull everything together, your AddHandler call now becomes:
AddHandler f_Cm.Closed, AddressOf f_Cm_Closed
And your method f_Cm_Closed becomes:
Private Sub f_Cm_Closed(sender As Object, e As ToolStripDropDownClosedEventArgs)
Dim f_Cm As Windows.Forms.ContextMenuStrip = sender
RemoveHandler f_Cm.Closed, AddressOf f_Cm_Closed
End Sub
As a final thought, I have no idea why you would want to remove the handler for the Closed event after the menu is closed. But this is how you would restructure your code to do it.
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.
I have 3 check boxes that I want to act as a radial button group, but my new job is in vb.net and WinForms.
My hope was to simplify the 3 event handlers by replacing the commented code with a function call like this:
Private Sub cbLinqQuery_CheckedChanged(sender As Object, e As EventArgs) handles cbLinqQuery.CheckedChanged
SafeCheckChg(cbDataTable, cbDataTable_CheckedChanged, cbLinqQuery.Checked)
'RemoveHandler cbDataTable.CheckedChanged, AddressOf cbDataTable_CheckedChanged
'cbDataTable.Checked = Not cbLinqQuery.Checked
'AddHandler cbDataTable.CheckedChanged, AddressOf cbDataTable_CheckedChanged
RemoveHandler cbArray.CheckedChanged, AddressOf cbArray_CheckedChanged
cbArray.Checked = Not cbLinqQuery.Checked
AddHandler cbArray.CheckedChanged, AddressOf cbArray_CheckedChanged
btnDefaultBoundData_Click(sender, e)
End Sub
Private Sub SafeCheckChg(ByRef cb As CheckBox, ByRef handler As EventHandler, checked As Boolean)
RemoveHandler cb.CheckedChanged, AddressOf handler
cb.Checked = Not checked
AddHandler cb.CheckedChanged, AddressOf handler.Clone
End Sub
But I've had no success passing the event handler as a parameter. I've tried passing it as an event handler, a delegate and a void but using it in the RemoveHandler/AddressOf call doesn't seem to be understood by the compiler.
Is there a method where I can get the event handler off of the passed object? Is there a type I can use as the parameter. Obviously I'm not desperate, this is in the name of better code not better functionality.
So Found a pretty close answer that worked with a small tweak:
Inspiration
Solution was simply to pass AddressOf foo as the parameter and remove the AddressOf from the RemoveHandler / AddHandler call. (Which for some reason I thought was a required part of the Add/RemoveHandler call and not a separate function call operating on a parameter.)
Final Code:
Private Sub cbLinqQuery_CheckedChanged(sender As Object, e As EventArgs) Handles cbLinqQuery.CheckedChanged
SafeCheckChg(cbDataTable, AddressOf cbDataTable_CheckedChanged, cbLinqQuery.Checked)
SafeCheckChg(cbArray, AddressOf cbArray_CheckedChanged, cbLinqQuery.Checked)
btnDefaultBoundData_Click(sender, e)
End Sub
Private Sub SafeCheckChg(ByRef cb As CheckBox, ByRef handler As EventHandler, checked As Boolean)
RemoveHandler cb.CheckedChanged, handler
cb.Checked = checked
AddHandler cb.CheckedChanged, AddressOf handler.Clone
End Sub
I'm using vb.net and winform. I am coming across an issue which I'm pounding my head against for the past few hours.
I have a main usercontrol which I added a groupbox and inside that groupbox, added a control like this:
main usercontrol
Me.GroupBox1.Controls.Add(Me.ctlWithDropDown)
user control ctlWithDropDown
Me.Controls.Add(Me.ddList)
Private Sub ddlList_SelectionChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ddlList.SelectionChanged
'some simple logic here to check if value changed
End Sub
The main usercontrol inherits the base class which has an event to set a value to true or false like so:
Public Event SetFlag(ByVal value As Boolean)
I want to know how I can trigger/set this boolean value from the dropdownlist when the SelectionChanged event is trigger. Any help on this issue?
Wire up an event handler for the drop down list:
AddHandler Me.ctlDropDown.SelectedIndexChanged, AddressOf ddlSelectedIndexChanged
Me.GroupBox1.Controls.Add(Me.ctlDropDown)
Make sure you create ddlSelectedIndexChanged in your control and have it fire the SetFlag Event:
Protected Sub ddlSelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
RaiseEvent SetFlag(True)
End Sub
I presume the me.ctlDropDown is something that you are making programmatically? If so then this sort of thing should work for you.
Public Sub Blah()
Dim ctlDropDown As New ComboBox
AddHandler ctlDropDown.SelectedIndexChanged, AddressOf IndexChangedHandler
Me.GroupBox1.Controls.Add(ctlDropDown)
End Sub
Private Sub IndexChangedHandler()
'Do whatever you need here.
End Sub
However, if this is not created at runtime should make an event handler like:
Private Sub IndexChangedHandler() Handles Me.ctlDropdown.SelectedIndexChanged
'Do whatever you need here.
End Sub
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