Areej Qadomi
Areej Qadomi

Reputation: 163

How to raise event from user control to another form vb.net

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

Answers (2)

Idle_Mind
Idle_Mind

Reputation: 39142

If I'm understanding correctly, you have...

  1. FormA creates FormB.
  2. FormB creates UserControlB.
  3. UserControlB raises "OK" event.
  4. FormB receives "OK" event.

...but you want an additional step of:

  1. FormA receives "OK" event.

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).

Option 1 - Pass References

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

Option 2 - "Bubble" the Event

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

Design Decisions

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

jmcilhinney
jmcilhinney

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

Related Questions