我尝试使用委托将信息从对话框表单传递到活动的MDI子表单(而不是父表单),但它仅接受一个数据,如何对多个数据执行此操作,如下图所示:
这是我到目前为止使用的:它仅接受文本框中的一个数据
MDI子表格:
Private Delegate Sub DoSearch(Msg As String)
Private PerformSearch As DoSearch
Private Sub InvokeFunc(Msg As String)
If PerformSearch IsNot Nothing Then
PerformSearch .Invoke(Msg)
End If
End Sub
Public Sub FuncDisplayMsg(Msg As String)
msg(Msg)
End Sub
Private Sub FrmParentLoad(sender As Object, e As EventArgs)
Dim FrmSecond As New frmSecondChild()
PerformSearch = AddressOf Me.FuncDisplayMsg
FrmSecond.InvokeDel = AddressOf Me.InvokeFunc
FrmSecond.Show()
End Sub
对话形式
Public Delegate Sub SearchInvoke(Msg As String)
Public InvokeSearch As SearchInvoke
Private Sub btnSubmit_Click(sender As Object, e As EventArgs)
If Me.InvokeSearch IsNot Nothing Then
InvokeSearch .Invoke(Me.txtMsg.Text)
End If
End Sub
我如何将控件(文本框,组合框和复选框)的值从对话框窗体传递到活动MDI子窗体(假设许多MDI子窗体已打开),如图所示,并在MDI子窗体中执行搜索
您似乎跳了很多圈。您不需要两个代表。您只需要一个。例如,如果您的对话框窗口具有如下代码:
Public Delegate Sub SearchInvoke(selection As Object, msg As String, chk1 As Boolean, chk2 As Boolean)
Public Property InvokeSearch As SearchInvoke
Private Sub btnSubmit_Click(sender As Object, e As EventArgs)
If Me.InvokeSearch IsNot Nothing Then
InvokeSearch.Invoke(cboSelection.SelectedItem, txtMsg.Text, chkBox1.Checked, chkBox2.Checked)
End If
End Sub
然后,您可以在主表单中简单地添加如下代码:
Public Sub FuncDisplayMsg(selection As Object, msg As String, chk1 As Boolean, chk2 As Boolean)
MessageBox.Show(msg)
End Sub
Private Sub FrmParentLoad(sender As Object, e As EventArgs)
Dim FrmSecond As New frmSecondChild()
FrmSecond.InvokeSearch = AddressOf Me.FuncDisplayMsg
FrmSecond.Show()
End Sub
或者,您可以将所有数据打包在一个对象中,然后将该一个对象作为参数发送给委托。例如,如果您有一个像这样的类:
Public Class DialogData
Public Property Selection As Object
Public Property Msg As String
Public Property Chk1 As Boolean
Public Property Chk2 As Boolean
End Class
然后,您可以定义您的委托并从对话框表单中调用它,如下所示:
Public Delegate Sub SearchInvoke(data As DialogData)
Public Property InvokeSearch As SearchInvoke
Private Sub btnSubmit_Click(sender As Object, e As EventArgs)
If Me.InvokeSearch IsNot Nothing Then
InvokeSearch.Invoke(New DialogData() With
{
.Selection = cboSelection.SelectedItem,
.Msg = txtMsg.Text,
.Chk1 = chkBox1.Checked,
.Chk2 = chkBox2.Checked
})
End If
End Sub
您可以像这样在您的主要形式中处理委托调用:
Public Sub FuncDisplayMsg(data As DialogData)
MessageBox.Show(data.Msg)
End Sub
Private Sub FrmParentLoad(sender As Object, e As EventArgs)
Dim FrmSecond As New frmSecondChild()
FrmSecond.InvokeSearch = AddressOf Me.FuncDisplayMsg
FrmSecond.Show()
End Sub
从技术上讲,事件只是一种特殊的委托,因此它们以相同的方式有效地工作。但是,用于事件的VB.NET语法与用于标准委托的语法有很大不同。由于处理事件是司空见惯的,因此您可能会发现将其实现为事件而不是标准委托更为“正常”。为了正确执行此操作,您需要创建一个EventArgs
包含用于保存数据的属性的类(类似于先前讨论的DialogData
类),例如:
Public Class SearchSubmittedEventArgs
Inherits EventArgs
Public Property Selection As Object
Public Property Msg As String
Public Property Chk1 As Boolean
Public Property Chk2 As Boolean
End Class
然后,您可以从对话框表单中声明并引发事件,如下所示:
Public Event SearchSubmitted As EventHandler(Of SearchSubmittedEventArgs)
Private Sub btnSubmit_Click(sender As Object, e As EventArgs)
RaiseEvent SearchSubmitted(Me, New SearchSubmittedEventArgs() With
{
.Selection = cboSelection.SelectedItem,
.Msg = txtMsg.Text,
.Chk1 = chkBox1.Checked,
.Chk2 = chkBox2.Checked
})
End Sub
然后,您可以像下面这样在您的主表单上处理事件:
Private WithEvents _dialog As frmSecondChild
Private Sub _dialog_SearchSubmitted(sender As Object, e As SearchSubmittedEventArgs) Handles _dialog.SearchSubmitted
MessageBox.Show(e.Msg)
End Sub
Private Sub FrmParentLoad(sender As Object, e As EventArgs)
_dialog = New frmSecondChild()
_dialog.Show()
End Sub
除了使用WithEvents
andHandles
关键字,您还可以选择使用and关键字手动附加事件处理程序AddHandler
。但是,如果您这样做了,别忘了稍后使用来分离它RemoveHandler
。
另一个选择是完全放弃委托或事件,而选择将某些业务对象提供给对话框表单。然后,对话框表单可以仅在该业务类上调用一个方法以根据需要执行搜索。例如,如果您创建了这样的业务类:
Public Class SearchBusiness
Public Sub PerformSearch(selection As Object, msg As String, chk1 As Boolean, chk2 As Boolean)
MessageBox.Show(msg)
End Sub
End Class
然后,您可以根据需要从如下对话框中调用它:
Public Property Business As SearchBusiness
Private Sub btnSubmit_Click(sender As Object, e As EventArgs)
If Business IsNot Nothing Then
Business.PerformSearch(cboSelection.SelectedItem, txtMsg.Text, chkBox1.Checked, chkBox2.Checked)
End If
End Sub
您可以从父表单显示对话框表单,如下所示:
Private Sub FrmParentLoad(sender As Object, e As EventArgs)
Dim FrmSecond As New frmSecondChild()
FrmSecond.Business = New SearchBusiness()
FrmSecond.Show()
End Sub
尽管在那种情况下,除非有所有都继承自的不同类型的搜索业务类,SearchBusiness
但当对话框本身可以创建业务对象时,让父窗体成为创建业务对象的事情似乎很可笑。这导致我进入下一个选择...
由于让对话框表单显式使用单独的业务类有点麻烦,因此我认为最好的方法是为搜索业务创建接口,如下所示:
Public Interface ISearchBusiness
Sub PerformSearch(selection As Object, msg As String, chk1 As Boolean, chk2 As Boolean)
End Interface
Public Class SearchBusiness
Implements ISearchBusiness
Public Sub PerformSearch(selection As Object, msg As String, chk1 As Boolean, chk2 As Boolean) Implements ISearchBusiness.PerformSearch
MessageBox.Show(msg)
End Sub
End Class
然后,您可以从对话框表单中调用它,如下所示:
Public Property Business As ISearchBusiness
Private Sub btnSubmit_Click(sender As Object, e As EventArgs)
If Business IsNot Nothing Then
Business.PerformSearch(cboSelection.SelectedItem, txtMsg.Text, chkBox1.Checked, chkBox2.Checked)
End If
End Sub
您可以从您的主表单中将适用的业务对象提供给对话框,方法与上述相同,如下所示:
Private Sub FrmParentLoad(sender As Object, e As EventArgs)
Dim FrmSecond As New frmSecondChild()
FrmSecond.Business = New SearchBusiness()
FrmSecond.Show()
End Sub
如果由于设计中的不明智限制,仅父窗体能够执行业务逻辑,那么您可以为对话框提供对父窗体的引用,而不是单独的业务对象。但是,在那种情况下,我绝对会坚持使用接口。这样,您可以在以后的日期中重构代码,使对话框具有实现相同接口而不是父窗体的单独业务对象。您不希望将糟糕的设计牢牢地钉在石头上。因此,如果您具有与上述相同的界面:
Public Interface ISearchBusiness
Sub PerformSearch(selection As Object, msg As String, chk1 As Boolean, chk2 As Boolean)
End Interface
然后,您仍然可以按照上述相同的方式从对话框中调用它:
Public Property Business As ISearchBusiness
Private Sub btnSubmit_Click(sender As Object, e As EventArgs)
If Business IsNot Nothing Then
Business.PerformSearch(cboSelection.SelectedItem, txtMsg.Text, chkBox1.Checked, chkBox2.Checked)
End If
End Sub
然后,您可以像这样在父表单中实现接口:
Public Class FrmParent
Implements ISearchBusiness
Public Sub PerformSearch(selection As Object, msg As String, chk1 As Boolean, chk2 As Boolean) Implements ISearchBusiness.PerformSearch
MessageBox.Show(msg)
End Sub
Private Sub FrmParentLoad(sender As Object, e As EventArgs)
Dim FrmSecond As New frmSecondChild()
FrmSecond.Business = Me
FrmSecond.Show()
End Sub
End Class
当窗体以模态显示时(即,使用ShowDialog
方法而不是Show
方法),这意味着直到关闭对话框窗体后,才会在父窗体中继续执行。因此,如果您不介意对话框窗体在完成之前一直在窃取并保持用户的关注(这是对话框窗口的典型行为),那么您可以模态地显示对话框窗体,然后读取其属性一旦关闭。例如,在您的主要形式中,您可以执行以下操作:
Private Sub FrmParentLoad(sender As Object, e As EventArgs)
Dim FrmSecond As New frmSecondChild()
FrmSecond.ShowDialog()
MessageBox.Show(FrmSecond.txtMsg.Text)
End Sub
但是,直接访问其他表单上的控件不是一个好习惯。如果对话框窗体公开每个数据的属性,然后主窗体通过这些属性访问数据,那就更好了。
到目前为止,这种方法是最简单的。只要您能做到这一点,这都是有道理的。这一点,对于实例的方式OpenFileDialog
,ColorDialog
和.NET框架内置的其他对话框。但是,这种设计有一个主要缺点,它可能会限制其使用。如果您需要在工作完成之前保持对话框打开状态,那么您就不能用这种方式真正做到这一点。例如,您可能希望在执行搜索时在对话框上显示某种进度条。或者,您可能希望考虑到业务逻辑中可能会出现一些验证错误的事实,此时您希望用户能够在对话框上进行更改,然后重试。在对话框用于数据输入的情况下,后者尤其重要。例如,如果使用对话框来允许用户提交新的销售订单,那么您不希望在成功提交销售订单之前关闭对话框。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句