How to pass an event Handler to a function that adds controls to that handler in VB? - vb.net

I made a class that handles the display of a set of controls. These controls are created at runtime. Because of that, I have to add them to an event handler at runtime as well. I made a function that allows me to specify the event handler to be used for some of the controls. The code looks like this:
Here's the main form
Dim displayObj as PackageDisplay = new PackageDisplay(AddressOf CheckBox_CheckedChanged)
The constructor does this
Public Sub New(ByRef eventHandler as Action(Of System.Object, EventArgs)
AddHandler chkExample.CheckedChanged, eventHandler
End Sub
However, I get the following error:
Value of type 'System.Action(Of Object, System.EventArgs)' cannot be converted to 'System.EventHandler'
It surely must be possible to pass an event handler and assign it, but I just don't know how. I've tried several different variations of this, but I can't figure out how to make this work. Any ideas?

You don't need to make one, use the stock System.EventHandler.

Related

RaiseEvent not being handled

I have made a custom event. What I intend to do is make a custom task pane invisible when I click the close button however it doesn't run my MainTaskPaneControl_HideTaskPane method. I'm clearly missing something simple but I'm unsure what I'm missing.
Code that runs first in ThisAddIn class:
Dim gen = New PowerPointDocSetUpMain()
AddHandler gen.HideTaskPane, AddressOf MainTaskPaneControl_HideTaskPane
Cancel Button in PowerPointDocSetUp class:
Private Sub ButtonCancel_Click(sender As Object, e As EventArgs) Handles ButtonCancel.Click
Dim main As PowerPointDocSetUpMain = New PowerPointDocSetUpMain
main.CloseMain()
End Sub
PowerPointDocSetUpMain class:
Public Event HideTaskPane()
Public Function CloseMain()
RaiseEvent HideTaskPane()
End Function
MainTaskPaneControl_HideTaskPane method in ThisAddIn class:
Friend Sub MainTaskPaneControl_HideTaskPane()
'Hide the requested task pane.
Globals.ThisAddIn.HideTaskPane()
End Sub
HideTaskPane method in ThisAddIn class:
Friend Function HideTaskPane() As System.Windows.Forms.UserControl
myTaskPane.Visible = False
End Function
You have two code snippets there that create PowerPointDocSetUpMain objects, so you're creating two different objects. One of them you register an event handler on and the other one you call CloseMain on. The one you call the method on has no event handler and the one with an event handler doesn't have the method called on it. It's hard to know what the exact solution should be because we don't really know how those code snippets relate to each other but the first two code snippets can't both create new objects. If the first one creates an object and registers an event handler then the second one must call CloseMain on that same object.
You're adding the Handler to the object gen here:
AddHandler gen.HideTaskPane, AddressOf MainTaskPaneControl_HideTaskPane
But in the Button_Click-method a new object main is created without adding a Handler to it. So the Handler for gen is never being called and the one for main does not exist.

Handles an Event from Control in another class

I want to fire an event in another class.
And my problem is I don't know how to make it.
I'm trying to use Inherits statement to my Form and add my class name to it, and it works as I hope:
Public Class Frm_Main_Copy
Inherits ToolStripMenuApp
'I have a ToolStripMenu that has declared before on my class and it sounds like this:
'Public Shared WithEvents Cat000x86_64App As ToolStripMenuItem
...
Private Sub IsClicked(ByVal sender As Object, ByVal e As EventArgs) Handles Cat000x86_64App.Click
End Sub
End Class
but the designer form messed up(returns a fatal error) and I should delete the Inherits statement, and the others.
Tried to act as form designer script(Trying to put this code to my class):
Friend WithEvents BlahBlah As RadioButton 'For example
It didn't worked,
Declaring a variable for my class and It didn't worked too
Searched on the Internet and it seems likely more complicated than I thought...
Anyone can help? Any help is appreciated.
A form is not a form unless it inherits, either directly or indirectly, the Form class. You cannot inherit any type that is not itself a form and expect your type to be a form. With that code, if ToolStripMenuApp is not a form then Frm_Main_Copy is not a form either, hence no form designer.
If what you're actually saying is that you have an instance of that ToolStripMenuApp that contains a TooStripMenuItem whose Click event you want to handle in Frm_Main_Copy then the first step is to not declare Cat000x86_64App as Shared. Frm_Main_Copy needs to declare a method capable of handling that event:
Private Sub IsClicked(ByVal sender As Object, ByVal e As EventArgs)
'...
End Sub
Note that there is no Handles clause because there's no WithEvents variable in that class whose event you are handling.
Next, Frm_Main_Copy must have access to the appropriate instance of ToolStripMenuApp. It's impossible for us to say how best to do that based on the information provided but it might be as simple as this:
Dim tsma As New ToolStripMenuApp
You then register your method as a handler for the appropriate event:
AddHandler tsma.Cat000x86_64App.Click, AddressOf IsClicked
If you use AddHandler, make sure to use RemoveHandler when you're done with either object. I suggest that you do some reading based on this information.

AddHandlers in VB.NET

I'm trying to dynamically creating dropdownList boxes, and I want trying to add AddHandlers to them so that when an item is selected in them, it fires an event, but also need to pass another variable, and I don't know what to put as the parameter for system.EventArgs. Please look at the code below to see the problem I'm having.
AddHandler inputDrop.SelectedIndexChanged, AddressOf selOption(inputDrop, ???, var1)
Protected Sub selOption(ByVal sender As Object, ByVal e As System.EventArgs, ByVal tableCount As String)
End Sub
What do I put (???) right here.
The error:
is an event, and cannot be called directly. Use a 'RaiseEvent' statement to raise an event.
In addition what Mike C already explained, if the signature of the event handler does not match the event, you can always wrap the event handler in another method, for example an anonymous one:
Protected Sub selOption(ender As Object, e As System.EventArgs, somestring As String)
End Sub
...
For i = 1 To 10
Dim cbox = new ComboBox()
Dim number = i ' local copy to prevent capturing of i '
AddHandler cbox.SelectedIndexChanged, Sub(s, e) selOption(s, e, "Hi! I am Number " & number)
Next
Now, when the index of the last ComboBox changes, the somestring parameter passed to selOption will be Hi! I am Number 10, while it will be Hi! I am Number 1 for the first ComboBox etc.
When you register an event handler, you don't specify the arguments at that time. You're basically just setting a reference to a delegate that will handle the event when it is raised.
AddHandler inputDrop.SelectedIndexChanged, AddressOf selOption
The most important thing is that the method signature of the event handler matches up exactly with the method signature defined by the event. I'm not sure that your method would work because you have that extra tableCount parameter specified. You will need to modify your method signature to be:
Protected Sub selOption(ByVal sender As Object, ByVal e As System.EventArgs)
I'm basing that off the definition of SelectedIndexChanged for Winforms. This event could be defined differently in another technology, such as ASP.net or WPF. Or if this is some custom class, it could be an entirely different signature altogether. However, typically most event handlers have a similar structure of a sender (the instance that raises the event) and some event arguments.
Then when inputDrop fires it's event (when the selected item changes), your code will get automatically called. The arguments passed to this method will be passed directly from inputDrop, you do not have to specify them.
Also, your AddHandler statement must exist inside a method or code block, it can't just live in the class definition. It's a statement that must be executed like any other piece of code, it's not a declaration.
And there is yet another way of doing it. Inherit the control in question and add a property like this:
Public Class MyComboBox : Inherits ComboBox
Public Property tableCount As String
End Class
Then set your custom value and add a handler as you would for a regular ComboBox:
combo.tableCount = tableCount
AddHandler combo.Click, AddressOf combo_Click
Inside combo_Click, CType sender to your inherited type, and get the value you stored previously:
Private Sub combo_Click(sender As Object, e As System.EventArgs)
Debug.WriteLine(CType(sender, WorkflowActionBox).tableCount)
End Sub
You will need to replace current usages of ComboBox with those of MyComboBox, where you want the new property to be available. Simple as opening your designer file and doing find/replace.

Using events for a dimmed variable

How can I use the event for a dimmed variable that is NOT a control.
This is my dimmed variable:
Dim engine As New Speech.Recognition.SpeechRecognitionEngine
I want to use the event "engine.SpeechRecognized".
You do it the same way you would for anything else where you wanted to add handlers explicitly:
AddHandler engine.SpeechRecognized, AddressOf HandleSpeechRecognized
See the documentation for the AddHandler statement for more information.
There are two ways to add error handlers in VB.NET. You can do so "manually" by using the AddHandler statement, such as:
Dim engine As New SpeechRecognitionEngine()
AddHandler engine.SpeechDetected, AddressOf OnSpeechDetected
With this approach, you would then need to manually implement the OnSpeechDetected event handler method, such as:
Private Sub OnSpeechDetected(ByVal sender As Object, ByVal e As SpeechDetectedEventArgs)
' Do something
End Sub
However, the second method is often easier. This second method is the way that events for controls are handled. However, it is only possible if your object variable is declared as a field (at the class level, outside of any method). All you need to do is add the keyword WithEvents before the variable name, such as:
Dim WithEvents engine As New SpeechRecognitionEngine()
Then, that variable name will show up in the left-side drop-down box at the top of your code window along with all your controls. When you select it in that drop-down box, you can then select any of its events in the right-side drop-down box and it will automatically create the event handler method for you:
Private Sub engine_SpeechDetected(ByVal sender As Object, ByVal e As SpeechDetectedEventArgs) Handles engine.SpeechDetected
End Sub

How to add event handler to local variable in VB.NET

I have a form in VB.NET that is used as a dialog in a mainform. Its instances are always locally defined, there's no field for it. When the user clicks the OK button in the dialog, it will fire an event with exactly one argument, an instance of one of my classes.
Since it is always a local variable, how can I add an event handler for that event? I've searched for myself and found something but I can't really figure it out...
Code for the event, a field in MyDialog:
public Event ObjectCreated(ByRef newMyObject as MyObject)
Code for the main form to call dialog : (never mind the syntax)
Dim dialog As New MyDialog()
dialog.ShowDialog(Me)
AddHandler ObjectCreated, (what do I put here?) //Or how do I add a handler?
As you can see I'm stuck on how to add a handler for my event. Can anyone help me? Preferrably with the best way to do it...
It's recommended, for consistency, that you use the same source and event args model as all system event handlers.
Create your own class inheriting from EventArgs, as:
Public Class MyObjectEventArgs
Inherits EventArgs
Public Property EventObject As MyObject
End Class
Then declare your event, and a handler method, like:
Public Event ObjectCreated As EventHandler(Of MyObjectEventArgs)
Private Sub Container_ObjectCreated(ByVal sender As Object, ByVal e As MyObjectEventArgs)
' Handler code here
End Sub
Then attach the handler to your event using:
AddHandler ObjectCreated, AddressOf Container_ObjectCreated
Additionally, you can use the Handles to attach to the event raised from your main form (assuming the name MainForm), as below:
Private Sub MainForm_ObjectCreated(ByVal sender As Object, ByVal e As MyObjectEventArgs) Handles MainForm.ObjectCreated
' Handler code here
End Sub
You need to write the subroutine that actually executes when the event is generated:
public Sub OnObjectCreated(ByRef newMyObject as MyObject)
...
End Sub
Then the handler is added:
AddHandler ObjectCreated, AddressOf OnObjectCreated
As a side note, ByRef does nothing here. All objects in VB are passed by reference. Only primitave variables (string, int, etc) by default use ByVal and can be set to ByRef