vb.net在每个子表单上侦听父表单事件

时间:2013-05-02 15:32:03

标签: vb.net

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

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

每个子页面都有一种方法可以监听要触发的ParentEvent()吗?基本上,我想要做的是在子页面上处理被触发的ParentEvent(),就像在子页面上单击一个按钮一样,如下所示:

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

2 个答案:

答案 0 :(得分:5)

这很容易做到,你只需要绕过VB的WithEventsHandles语法来实现它。

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

在处理子表单之前始终确保删除事件处理程序非常重要(否则最终会导致内存泄漏)。

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

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

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

唯一的另一个警告是,您无法在父表单的构造函数中创建任何子表单,因为您在构造期间最终会自我引用。

答案 1 :(得分:3)

不确定

将公共事件添加到父表单:

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还是简单的自由浮动窗口,都可以使用此方法。

Screenshot

完整代码

ParentForm Designer

<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 Designer

<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 Designer

<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