I know there is a lot of information regarding the above, but I do not grasp how to do this correctly, so I thought using a real life problem may help to click it for me and others.
So in class A I have defined an event method
Public Sub textChangedMethod(ByVal textedChanged As Boolean)
' do some code on properties of this class only
End Sub
What I need to happen is I need some other class to raise this method,
I have a concept but its totally wrong.
At the moment I pass an instance of class A to the another class so it can reference the event (this must be wrong)
Dim UI As New newClassDialog(Me) 'class A
In this new class I have the event handler
Public Event textChanged(ByVal textedChanged As Boolean)
So in the constructor of the new class I can now add the handler
Public Sub New(ByRef classA As Class A)
' This call is required by the designer.
InitializeComponent()
AddHandler textChanged, AddressOf classA.textChangedMethod
End Sub
Now of course I can raise the event like so
RaiseEvent textChanged(True)
Basically passing in the class seems ridiculous in my eyes, so using this example is there a 'proper' way of doing this?
Thanks
It seems that you are inverting the roles. In this context the class that raises the event shouldn't know who handles the event. It is the responsability of class that instantiate the newClassDialog to add the event handler for the events raised by the called class
Dim UI As New newClassDialog(Me)
AddHandler UI.textchanged, AddressOf Me.textChangedMethod
Related
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.
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.
I am wondering if it is possible to make and Raise an event from a class, to a form? I have a class that just loops through itself continually, but when a condition is met I want a button to become visible on a form. I am looking into different ways of accomplishing this. It is probably worth mentioning that I am multithreading and this loop is being run in a different thread than the UI is at. Which is why I am hoping it is possible to raise an event and that will jump over to the UI thread and make the button visible then come back to where it was in the loop.
Any suggestions or direction is appreciated.
Something like this would work,
Public Class MyClass
Public Event MyEvent()
Sub DoStuff()
RaiseEvent MyEvent
End Sub
Public Class
Public Class MyForm
Public Sub HandleEvent()
'can be called from another thread, so use invoke
Me.Invoke(Sub() MyButton.Visible = true )
End Sub
End Class
Dim mMyClass = New MyClass
Dim mMyForm = New MyForm
AddHandler mMyClass.MyEvent, AddressOf mMyForm.HandleEvent()
As long as you remember to use .Invoke when updating the UI if your event is coming from another thread, there is no issue with having a form handle events from any source.
I think here is a possible solution:
1) pass parent form to the class as a parameter;
2) in parent form, invoke the function
Private Delegate Sub DoStuffDelegate()
Private Sub DoStuff()
If Me.InvokeRequired Then
Me.Invoke(New DoStuffDelegate(AddressOf DoStuff))
Else
btn.Visible = true
End If
End Sub
3) in class, call it as parentform.DoStuff()
check the syntax as I typed it.
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
I have a "partial" class in VB.NET. Half of it is auto generated by a code generation tool. That half implements INotifyPropertyChanged, so any properties in that part of the partial class raise the PropertyChanged event.
In my "custom" part of the class, I declare another property that depends on one of the properties in the auto-generated side. Therefore, when that auto-generated property changes, I also want to raise a PropertyChanged event on my custom property that depends on it.
If I go into the generated part of the class and raise the event there, that will get overwritten if I ever re-generate that part, so I don't want to do that. I would rather add an event handler in my side of the partial class that checks if the generated property changed, and if so, raise another event for my custom property.
I'm trying to write this to hook my own event, but it's not working:
Private Sub MyProperty_PropertyChangedHandler( _
ByVal sender As Object, ByVal e As PropertyChangedEventArgs _
) Handles Me.PropertyChanged
Select Case e.PropertyName
Case "AutoGenProperty"
RaiseEvent PropertyChanged(Me, _
New PropertyChangedEventArgs("MyProperty"))
End Select
End Sub
I'm assuming it's because normally you'd use the WithEvents keyword to tell the compiler that you're subscribing to events from that object. I don't have a clue how to do this inside of the class that's actually raising the event, or if that's even possible.
In your constructor, you need something on the lines of
AddHandler PropertyChanged, addressof MyProperty_PropertyChangedHandler
and remove the "Handles Me.PropertyChanged" from your event handler, basically your adding the event handler manually
where "PropertyChanged" is the name of the event you want to catch.
UPDATE
You can't do that because the the ctor is in the auto generated portion of the class.
So you can use the following idiom to add the handler for you.
You're going to specify a private class inside your class, and put it on as a private member on your new class, when the private member is constructed you add the handler for the event.
Public Partial MyClass
private class MyInitialiser
public sub new(byval myParent as MyClass)
Addhandler myParent.PropertyChanged, addressof myParent.MyProperty_PropertyChangedHandler
end sub
end class
private _myInitialiser as new MyInitialiser(me)
. . .
End Class
The above is untested, but I've done this lots of times before.
Hope it helps :)