Reputation: 163
I am not familiar with user controls. I have user control with OK and Cancel buttons, I add this user control to an empty form during run time, I have another form which I called "Main Form", In the code I open the empty form and add the user control, after that I want to raise an event (on the OK button) from the user control (or from the empty form I don't know!) to the Main form! I searched the net and found way to create an event and raise the event in the same form. I tried to do the same thing between different forms but I don't know how to do that.
create event
Public Event OKEvent As EventHandler
raise event
Protected Overridable Sub OnbtnOKClick(e As EventArgs)
AddHandler OKEvent , AddressOf btnOKClickHandler
RaiseEvent OKEvent(Me, e)
End Sub
event Sub
Sub btnOKClickHandler(sender As Object, e As EventArgs)
'Event Handling
'My event code
End Sub
handle my event on btnOK.click event
Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click
OnbtnOKClick(e)
End Sub
Okey, that all code works in the same form, maybe its messy but that what I found on the net, I want to make similar thing but on different forms, how can I organize my code?
Upvotes: 1
Views: 13806
Reputation: 39142
If I'm understanding correctly, you have...
...but you want an additional step of:
The problem here is that FormA has no reference to UserControlB because FormB was the one that created the UserControl. An additional problem is that FormB may have no idea who FormA is (depending on how you've got it setup).
If you want both FormB and FormA to respond to a SINGLE "OK" event (generated by the UserControl), then you'd have to somehow have a reference to all three players in the same place so that the event can be properly wired up. The logical place to do this would be in FormB as that is where the UserControl is created. To facilitate that, however, you'd have to modify FormB so that a reference to FormA is somehow passed to it. Then you can wire up the "OK" event directly to the handler in FormA when FormB creates its instance of UserControlB:
Public Class FormA
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim frmB As New FormB(Me) ' pass reference to FormA into FormB via "Me" and the Constructor of FormB
frmB.Show()
End Sub
Public Sub ucB_OKEvent()
' ... do something in here ...
Debug.Print("OK Event received in FormA")
End Sub
End Class
Public Class FormB
Private _frmA As FormA
Public Sub New(ByVal frmA As FormA)
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
_frmA = frmA ' store reference to FormA so we can use it later
End Sub
Private Sub FormB_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim ucB As New UserControlB
ucB.Location = New Point(10, 10)
AddHandler ucB.OKEvent, AddressOf _frmA.ucB_OKEvent ' wire up the "OK" event DIRECTLY to the handler in our stored reference of FormA
Me.Controls.Add(ucB)
End Sub
End Class
Public Class UserControlB
Public Event OKEvent()
Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click
RaiseEvent OKEvent()
End Sub
End Class
Another option is "bubble" the event from FormB up to FormA. In this scenario, FormB will have no idea who FormA is, so no reference will be passed. Instead, FormB will have its own "OK" event that is raised in response to receiving the original "OK" event from UserControlB. FormA will get the "OK" notification from the UserControl, just not directly:
Public Class FormA
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim frmB As New FormB
AddHandler frmB.OKEvent, AddressOf frmB_OKEvent
frmB.Show()
End Sub
Private Sub frmB_OKEvent()
' ... do something in here ...
Debug.Print("OK Event received from FormB in FormA")
End Sub
End Class
Public Class FormB
Public Event OKEvent()
Private Sub FormB_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim ucB As New UserControlB
ucB.Location = New Point(10, 10)
AddHandler ucB.OKEvent, AddressOf ucB_OKEvent
Me.Controls.Add(ucB)
End Sub
Private Sub ucB_OKEvent()
Debug.Print("OK Event received from UserControl in FormB")
RaiseEvent OKEvent()
End Sub
End Class
Public Class UserControlB
Public Event OKEvent()
Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click
RaiseEvent OKEvent()
End Sub
End Class
You have to make a design decision here. Who is the source of the "OK" event? Should it be the UserControl or FormB? Will the UserControl ever be used in different forms (other than FormB)? Will FormB ever be used with Forms other then FormA? These answers may help you decide which approach is better...or may lead you to rethink how you've designed your current solution; you may need to change it altogether.
Upvotes: 1
Reputation: 54457
You don't raise an event "to" anywhere. The whole point of events is that you don't have to care who is listening. It's up to the whoever wants to react to the event to handle it and whoever raised the event never has to know about them.
So, all you need to do in this case is have the main form handle the appropriate event(s) of the user control. The user control is a control like any other and the event is an event like any other so the main form handles the event of the user control like it would handle any other event of any other control. Where you create the user control, use an AddHandler
statement to register a handler for the event you declared in the user control.
EDIT:
The OnbtnOKClick
method that you have shown above should not look like this:
Protected Overridable Sub OnbtnOKClick(e As EventArgs)
AddHandler OKEvent , AddressOf btnOKClickHandler
RaiseEvent OKEvent(Me, e)
End Sub
but rather like this:
Protected Overridable Sub OnbtnOKClick(e As EventArgs)
RaiseEvent OKEvent(Me, e)
End Sub
Also, the btnOKClickHandler
method should be in the main form, not the user control. As I said in my answer, it's the main form that handles the event. That means that the event handler is in the main form. As I also said, when you create the user control in the main form, that is where you register the event handler, e.g.
Dim uc As New SomeUserControl
AddHandler uc.OKEvent, AddressOf btnOKClickHandler
As I hope you have absorbed in your reading, if you use AddHandler
to register an event handler then you need a corresponding RemoveHandler
to unregister it when the object is finished with.
Upvotes: 1