我正在尝试在父窗体上实现一个函数,当事件触发时,我想对所有打开的子窗体执行操作。因为任何给定的子表单可能在给定时间打开,也可能不打开,我无法直接从父表单上的事件处理它:即,由于当时可能不启动Child1,因此无法执行以下操作:
--Parent Form--
Public Sub ParentEvent()
DoParentAction()
DoChild1Action()
DoChild2Action()
End Sub
每个子页面都有一种方法可以监听要触发的ParentEvent()吗?基本上,我想要做的是在子页面上处理被触发的ParentEvent(),就像在子页面上单击一个按钮一样,如下所示:
--Child1--
Public Sub ChildEvent() Handles ParentForm.DoParentAction()
DoChild1Action()
End Sub
答案 0 :(得分:5)
这很容易做到,你只需要绕过VB的WithEvents
和Handles
语法来实现它。
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还是简单的自由浮动窗口,都可以使用此方法。
<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
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
<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
Public Class ChildForm1
Public Sub ParentEventFired(ByVal timestamp As DateTime)
Label1.Text = "Child 1: Parent Event Fired (" & timestamp.ToLongTimeString() & ")"
End Sub
End Class
<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
Public Class ChildForm2
Public Sub ParentEventFired(ByVal timestamp As DateTime)
Label1.Text = "Child 2: Parent Event Fired (" & timestamp.ToLongTimeString() & ")"
End Sub
End Class