1

我不熟悉用户控件。我有带有确定和取消按钮的用户控件,我在运行时将此用户控件添加到一个空表单,我有另一个表单,我称为“主表单”,在代码中我打开空表单并添加用户控件,之后我想从用户控件(或从我不知道的空窗体!)向主窗体引发一个事件(在 OK 按钮上)! 我在网上搜索并找到了创建事件并以相同形式引发事件的方法。我试图在不同的表格之间做同样的事情,但我不知道该怎么做。

创建事件

Public Event OKEvent As EventHandler

引发事件

Protected Overridable Sub OnbtnOKClick(e As EventArgs)
    AddHandler OKEvent , AddressOf btnOKClickHandler
    RaiseEvent OKEvent(Me, e)
End Sub

事件子

Sub btnOKClickHandler(sender As Object, e As EventArgs)
        'Event Handling
        'My event code 
    End Sub

在 btnOK.click 事件上处理我的事件

Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click
        OnbtnOKClick(e)
End Sub

好吧,所有代码都以相同的形式工作,也许它很乱,但是我在网上找到的,我想做类似的东西,但形式不同,我该如何组织我的代码?

4

2 回答 2

1

您不会在任何地方“向”提出事件。事件的全部意义在于你不必关心谁在听。这取决于想要对事件做出反应的人来处理它,而提出事件的人永远不必知道它们。

因此,在这种情况下,您需要做的就是让主窗体处理用户控件的适当事件。用户控件和其他控件一样,事件也是其他控件,因此主窗体处理用户控件的事件就像它处理任何其他控件的任何其他事件一样。在您创建用户控件的位置,使用AddHandler语句为您在用户控件中声明的事件注册处理程序。

编辑:

您上面显示的OnbtnOKClick方法不应如下所示:

Protected Overridable Sub OnbtnOKClick(e As EventArgs)
    AddHandler OKEvent , AddressOf btnOKClickHandler
    RaiseEvent OKEvent(Me, e)
End Sub

而是像这样:

Protected Overridable Sub OnbtnOKClick(e As EventArgs)
    RaiseEvent OKEvent(Me, e)
End Sub

此外,该btnOKClickHandler方法应该在主窗体中,而不是用户控件。正如我在回答中所说,它是处理事件的主要形式。这意味着事件处理程序位于主窗体中。正如我还说过的,当您在主窗体中创建用户控件时,就是您注册事件处理程序的地方,例如

Dim uc As New SomeUserControl

AddHandler uc.OKEvent, AddressOf btnOKClickHandler

正如我希望您在阅读中专心致志的那样,如果您使用AddHandler注册一个事件处理程序,那么您需要一个对应RemoveHandler的来在对象完成时取消注册它。

于 2017-05-13T12:44:07.690 回答
1

如果我理解正确,你有...

  1. FormA 创建 FormB。
  2. FormB 创建 UserControlB。
  3. UserControlB 引发“OK”事件。
  4. FormB 收到“OK”事件。

...但您需要额外的步骤:

  1. FormA 收到“OK”事件。

这里的问题是 FormA 没有对 UserControlB 的引用,因为 FormB 是创建 UserControl 的那个。另一个问题是 FormB 可能不知道 FormA 是谁(取决于您如何设置它)。

选项 1 - 通过参考

如果您希望 FormB 和 FormA 都响应单个“OK”事件(由 UserControl 生成),那么您必须以某种方式在同一位置引用所有三个玩家,以便可以正确连接事件. 执行此操作的逻辑位置将在 FormB 中,因为这是创建 UserControl 的位置。然而,为了方便起见,您必须修改 FormB 以便对 FormA 的引用以某种方式传递给它。然后,当 FormB 创建其 UserControlB 实例时,您可以将“OK”事件直接连接到 FormA 中的处理程序:

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

选项 2 - “冒泡”事件

另一种选择是将事件从FormB“冒泡”到FormA。在这种情况下,FormB 将不知道 FormA 是谁,因此不会传递任何引用。相反,FormB 将拥有自己的“OK”事件,以响应从 UserControlB 接收原始“OK”事件而引发。FormA 将从 UserControl 获得“OK”通知,而不是直接:

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

设计决策

你必须在这里做出设计决定。谁是“OK”事件的来源?它应该是 UserControl 还是 FormB?UserControl 会以不同的形式(FormB 除外)使用吗?FormB 会与 FormA 以外的表单一起使用吗?这些答案可能会帮助您决定哪种方法更好……或者可能会导致您重新考虑如何设计当前的解决方案;你可能需要完全改变它。

于 2017-05-13T14:50:11.080 回答