i am Handling Event in vb.net
AddHandler ButtonOne.Click, AddressOf ButtonClick
Private Sub ButtonClick(ByVal ctrl As Office.CommandBarButton, ByRef Cancel As Boolean)
//do stuff
End sub
But my event calling twice.when i click onces on button and in another method also
i am handling same event
Private Sub AddToolbar()
// do something
AddHandler firstButton.Click, AddressOf ButtonClick
End
How to resovle this issue ?
plz help me
As Hans pointed out.... you are calling the button click twice... Also see below
AddHandler ButtonOne.Click, AddressOf ButtonClick 'You dont really need this if you add a handler to the sub see below...
Private Sub ButtonClick(ByVal ctrl As Office.CommandBarButton, ByRef Cancel As Boolean) Handles ButtonOne.Click
//do stuff
End sub
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 have a function GetLogs that calls another function GetHistoricalData. GetHistoricalData is running in a thread and at the end of it, it fires an event AsyncLoggingRequestFinished. What I want is to wait in GetLogs for the event to be raised. Here is a code example to make thinks clearer:
Private Sub GetLogs
_historicalLogging = new HistoricalLogging()
AddHandler _historicalLogging.AsyncLoggingRequestFinished, AddressOf _historicalLogging_AsyncLoggingRequestFinished
_historicalLogging.GetHistoricalData("LogCategory")
'I want to wait here and after the event raised, keep going
End Sub
Private Sub _historicalLogging_AsyncLoggingRequestFinished(ByVal sender As Object, ByVal e As AsyncRequestSuccessArgs)
RemoveHandler _historicalLogging.AsyncLoggingRequestFinished, AddressOf _historicalLogging_AsyncLoggingRequestFinished
For Each entry in _historicalLogging.Entries
'DoSomething
Next
End Sub
Note: HistoricalLogging is an object from a DLL. I cant change any code of that object
Not the best way to do it but it works
Private Sub GetLogs()
_historicalLogging = New HistoricalLogging()
AddHandler _historicalLogging.AsyncLoggingRequestFinished, AddressOf _historicalLogging_AsyncLoggingRequestFinished
_historicalLogging.GetHistoricalData("LogCategory")
'I want to wait here and after the event raised, keep going
Do Until EventRaisen
Application.DoEvents()
Loop
EventRaisen = False
'Code After The Event Has Raisen
End Sub
Dim EventRaisen As Boolean = False
Private Sub _historicalLogging_AsyncLoggingRequestFinished(ByVal sender As Object, ByVal e As AsyncRequestSuccessArgs)
RemoveHandler _historicalLogging.AsyncLoggingRequestFinished, AddressOf _historicalLogging_AsyncLoggingRequestFinished
For Each entry In _historicalLogging.Entries
EventRaisen = True
'DoSomething
Next
End Sub
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
I have a form that has a start button (to allow users to run the processes over and over if they wish), and I want to send a btnStart.Click event when the form loads, so that the processes start automatically.
I have the following function for the btnStart.Click event, but how do I actually tell Visual Basic 'Pretend someone has clicked the button and fire this event'?
I've tried going very simple, which essentially works. However, Visual Studio gives me a warning Variable 'sender' is used before it has been assigned a value, so I'm guessing this is not really the way to do it:
Dim sender As Object
btnStart_Click(sender, New EventArgs())
I have also tried using RaiseEvent btnStart.Click, but that gives the following error:
'btnStart' is not an event of 'MyProject.MyFormClass
Code
Imports System.ComponentModel
Partial Public Class frmProgress
Private bw As BackgroundWorker = New BackgroundWorker
Public Sub New()
InitializeComponent()
' Set up the BackgroundWorker
bw.WorkerReportsProgress = True
bw.WorkerSupportsCancellation = True
AddHandler bw.DoWork, AddressOf bw_DoWork
AddHandler bw.ProgressChanged, AddressOf bw_ProgressChanged
AddHandler bw.RunWorkerCompleted, AddressOf bw_RunWorkerCompleted
' Fire the 'btnStart.click' event when the form loads
Dim sender As Object
btnStart_Click(sender, New EventArgs())
End Sub
Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
If Not bw.IsBusy = True Then
' Enable the 'More >>' button on the form, as there will now be details for users to view
Me.btnMore.Enabled = True
' Update the form control settings so that they correctly formatted when the processing starts
set_form_on_start()
bw.RunWorkerAsync()
End If
End Sub
' Other functions exist here
End Class
You should send a button as sender into the event handler:
btnStart_Click(btnStart, New EventArgs())
Steps in involved in raising an event is as follows,
Public Event ForceManualStep As EventHandler
RaiseEvent ForceManualStep(Me, EventArgs.Empty)
AddHandler ForceManualStep, AddressOf ManualStepCompletion
Private Sub ManualStepCompletion(sender As Object, e As EventArgs)
End Sub
So in your case, it should be as below,
btnStart_Click(btnStart, EventArgs.Empty)
Just Call
btnStart.PerformClick()
You are trying to implement a bad idea. Actually, you have to make a subroutine to accomplish these kind of tasks.
Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
call SeparateSubroutine()
End Sub
private sub SeparateSubroutine()
'Your code here.
End Sub
And then whereever you want to call the btnStart's click event, just call that SeparateSubroutine. This should be a correct way in your case.
You can subclass the button and make its OnClick Method public as I described here.