0

我正在尝试在我的父表单上实现一个功能,当事件触发时,我想对所有打开的子表单执行操作。因为任何给定的子表单在给定时间可能会或可能不会打开,所以我无法直接从父表单上的事件处理它:即,不能执行以下操作,因为当时可能不会启动 Child1:

--Parent Form--
Public Sub ParentEvent()
    DoParentAction()
    DoChild1Action()
    DoChild2Action()
End Sub

每个子页面上是否有办法监听 ParentEvent() 被触发?本质上,我想做的是在子页面上处理被触发的 ParentEvent(),就像在子页面上单击按钮一样,如下所示:

--Child1--
Public Sub ChildEvent() Handles ParentForm.DoParentAction()
    DoChild1Action()
End Sub
4

2 回答 2

6

这很容易做到,您只需要绕过 VBWithEventsHandles语法即可。

Public Class ParentForm
    Event OnDoSomething()

    Private Sub DoSomething()
         RaiseEvent OnDoSomething()
    End Sub
End Class

进而

Public Class ChildForm
   Public Sub New()
        InitializeComponent()
        AddHandler ParentForm.OnDoSomething, AddressOf DoSomething
    End Sub

    Private Sub DoSomething()
        ' do something
    End Sub

    Private Sub ChildForm_FormClosing(ByVal sender As System.Object, _
                ByVal e As System.Windows.Forms.FormClosingEventArgs) _
                Handles MyBase.FormClosing
        RemoveHandler ParentForm.OnDoSomething, AddressOf DoSomething
    End Sub
End Class

务必确保在处置子表单之前删除事件处理程序(否则最终会导致内存泄漏),这一点很重要。

以上假设您使用的是 VB 默认实例ParentForm- 如果不是,显然您必须相应地引用事物。更好的方法可能是让父级在构造函数中成为参数,例如:

 Public Sub New(ByVal parent as ParentForm)
    InitializeComponent()
    AddHandler parent.OnDoSomething, AddressOf DoSomething
 End Sub  

当然,还要修改该RemoveHandler部分(您需要保留对父级的引用)。ParentChanged如果这是一个 MDI 应用程序,另一种选择是在事件中挂钩/取消挂钩。

唯一需要注意的是,您不能在父窗体的构造函数中创建任何子窗体,因为在构造过程中最终会出现自引用。

于 2013-05-02T16:31:13.077 回答
5

当然。

向父窗体添加公共事件:

Public Event EventFired(ByVal timestamp As DateTime)

在每个子窗体中,添加一个处理程序:

Public Sub ParentEventFired(ByVal timestamp As DateTime)
    Label1.Text = "Child 1: Parent Event Fired (" & timestamp.ToLongTimeString() & ")"
End Sub

创建子表单时,添加一个处理程序:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim l_child1 = New ChildForm1()
    AddHandler Me.EventFired, AddressOf l_child1.ParentEventFired
    l_child1.Show(Me)
End Sub

无论您使用的是 MDI 还是简单的自由浮动窗口,您都可以使用这种方法。

截屏

完整代码

父窗体设计器

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class ParentForm
    Inherits System.Windows.Forms.Form

    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.Button1 = New System.Windows.Forms.Button
        Me.Button2 = New System.Windows.Forms.Button
        Me.Button3 = New System.Windows.Forms.Button
        Me.SuspendLayout()
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(12, 12)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(166, 23)
        Me.Button1.TabIndex = 0
        Me.Button1.Text = "Open Child 1"
        Me.Button1.UseVisualStyleBackColor = True
        '
        'Button2
        '
        Me.Button2.Location = New System.Drawing.Point(12, 41)
        Me.Button2.Name = "Button2"
        Me.Button2.Size = New System.Drawing.Size(166, 23)
        Me.Button2.TabIndex = 0
        Me.Button2.Text = "Open Child 2"
        Me.Button2.UseVisualStyleBackColor = True
        '
        'Button3
        '
        Me.Button3.Location = New System.Drawing.Point(12, 231)
        Me.Button3.Name = "Button3"
        Me.Button3.Size = New System.Drawing.Size(166, 23)
        Me.Button3.TabIndex = 0
        Me.Button3.Text = "Fire Event"
        Me.Button3.UseVisualStyleBackColor = True
        '
        'ParentForm
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(292, 266)
        Me.Controls.Add(Me.Button3)
        Me.Controls.Add(Me.Button2)
        Me.Controls.Add(Me.Button1)
        Me.Name = "ParentForm"
        Me.Text = "ParentForm"
        Me.ResumeLayout(False)

    End Sub
    Friend WithEvents Button1 As System.Windows.Forms.Button
    Friend WithEvents Button2 As System.Windows.Forms.Button
    Friend WithEvents Button3 As System.Windows.Forms.Button
End Class

ParentForm 代码背后

Public Class ParentForm

    Public Event EventFired(ByVal timestamp As DateTime)

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim l_child1 = New ChildForm1()
        AddHandler Me.EventFired, AddressOf l_child1.ParentEventFired
        l_child1.Show(Me)
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim l_child2 = New ChildForm2()
        AddHandler Me.EventFired, AddressOf l_child2.ParentEventFired
        l_child2.Show(Me)
    End Sub

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        RaiseEvent EventFired(DateTime.Now)
    End Sub

End Class

ChildForm1 设计器

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class ChildForm1
    Inherits System.Windows.Forms.Form

    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.Label1 = New System.Windows.Forms.Label
        Me.SuspendLayout()
        '
        'Label1
        '
        Me.Label1.AutoSize = True
        Me.Label1.Location = New System.Drawing.Point(12, 9)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(39, 13)
        Me.Label1.TabIndex = 0
        Me.Label1.Text = "Label1"
        '
        'ChildForm1
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(292, 266)
        Me.Controls.Add(Me.Label1)
        Me.Name = "ChildForm1"
        Me.Text = "ChildForm1"
        Me.ResumeLayout(False)
        Me.PerformLayout()

    End Sub
    Friend WithEvents Label1 As System.Windows.Forms.Label
End Class

ChildForm1 代码后面

Public Class ChildForm1

    Public Sub ParentEventFired(ByVal timestamp As DateTime)
        Label1.Text = "Child 1: Parent Event Fired (" & timestamp.ToLongTimeString() & ")"
    End Sub

End Class

ChildForm2 设计器

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class ChildForm2
    Inherits System.Windows.Forms.Form

    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.Label1 = New System.Windows.Forms.Label
        Me.SuspendLayout()
        '
        'Label1
        '
        Me.Label1.AutoSize = True
        Me.Label1.Location = New System.Drawing.Point(12, 9)
        Me.Label1.Name = "Label1"
        Me.Label1.Size = New System.Drawing.Size(39, 13)
        Me.Label1.TabIndex = 1
        Me.Label1.Text = "Label1"
        '
        'ChildForm2
        '
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.ClientSize = New System.Drawing.Size(292, 266)
        Me.Controls.Add(Me.Label1)
        Me.Name = "ChildForm2"
        Me.Text = "ChildForm2"
        Me.ResumeLayout(False)
        Me.PerformLayout()

    End Sub
    Friend WithEvents Label1 As System.Windows.Forms.Label
End Class

ChildForm2 代码背后

Public Class ChildForm2

    Public Sub ParentEventFired(ByVal timestamp As DateTime)
        Label1.Text = "Child 2: Parent Event Fired (" & timestamp.ToLongTimeString() & ")"
    End Sub

End Class
于 2013-05-02T17:03:46.290 回答