vb.net 侦听每个子窗体上的父窗体事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16342016/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 13:28:16  来源:igfitidea点击:

vb.net listen for parent form event on each child form

vb.net

提问by scholzr

I am trying to implement a function on my parent form, that when the event fires, I want to perform actions on all of the child forms that are open. Because any given child form may or may not be open at a given time, I can't handle it directly from the event on the parent form: i.e., cant do the following as Child1 may not be initiated at the time:

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

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

Is there a way on each child page to listen for ParentEvent() to be fired? essentially, what I want to do is handle the ParentEvent() being fired, on the child page the same as if a button was clicked on the child page, something like this:

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

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

回答by J...

This is easy to do, you just have to step around VB's WithEventsand Handlessyntax to get at it.

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

Public Class ParentForm
    Event OnDoSomething()

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

and then

进而

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

It's important to always make sure the event handler is removed before disposing the child form (else you end up with a memory leak).

务必确保在处理子窗体之前删除事件处理程序(否则最终会出现内存泄漏)。

The above assumes you are using the VB default instance of ParentForm- if you're not, obviously you have to reference things accordingly. A better approach might be to make the parent an argument in the constructor like:

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

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

also, of course, modifying the RemoveHandlersection as well (you'd need to keep a reference to the parent). Another option is to hook/unhook in the ParentChangedevent if this is an MDI application.

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

The only other caveat is that you can't create any of the child forms in the constructor of the parent form since you end up with self-reference during construction.

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

回答by JDB still remembers Monica

Sure.

当然。

Add a public event to the parent form:

向父表单添加公共事件:

Public Event EventFired(ByVal timestamp As DateTime)

In each child form, add a handler:

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

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

When you create the child form, add a handler:

创建子窗体时,添加一个处理程序:

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

You can use this approach whether you are using an MDI or simply free-floating windows.

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

Screenshot

截屏

FULL CODE

完整代码

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 Code Behind

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

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 Code Behind

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

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 Code Behind

ChildForm2 代码背后

Public Class ChildForm2

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

End Class