对于大多数可视化的信息系统而言,经常遇到多个窗体交互的现象,其中又以子窗体和父窗体交互居多,刚刚做了一个项目,遇到了很多这种现象,又从网上收集了一些这方面的知识,现在总结一下,做个备份。
信息系统无非是信息获取、后台处理、显示的过程。子窗体和父窗体的交互大多是显示的需要。如果把子窗体和父窗体作为两个对象的话,他们之间的相互操作有几个关键点要理清楚:①操作对象和被操作对象;②触发时点和触发事件;③被操作对象的操作。这其中第二点最为关键,关于怎样触发事件、传递消息和接收消息有很多方法,这是我们要讨论的重点。父窗体操作子窗体是比较简单的,通常子窗体都是父窗体类的一个对象,父窗体想操作子窗体,只需要在触发事件中调用子窗体对象中已暴露的接口,想让子窗体做什么,只需要在接口中实现就可以了。
代码示例如下(VB.net,自动生成代码略去,以下同):

Code
1
Public Class FormParentClass FormParent
2
3
Inherits System.Windows.Forms.Form
4
5
Dim obFormChild As New FormChild
6
7
Private Sub Button1_Click()Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
8
9
obFormChild.DoAction()
10
11
End Sub
12
13
End Class
14
15
Public Class FormChildClass FormChild
16
17
Inherits System.Windows.Forms.Form
18
19
Public Function DoAction()Function DoAction() As Boolean
20
21
'添加动作内容
22
23
End Function
24
25
End Class
26
下面重点说明子窗体如何操作父窗体的几种方法。
1. 将父窗体实例传递给子窗体作为自己的对象。这个方法等于把父窗体操作子窗体倒过来。但是父窗体一般承载的信息比较多,而且一般不止一个子窗体,这样做容易造成对象的混乱,而且影响类自己的封闭性,效率方面不知道有没有影响(笔者学识尚浅,请高人指教),但是总觉得不优雅,呵呵。

Code1
1
Public Class FormParentClass FormParent
2
3
Inherits System.Windows.Forms.Form
4
5
Dim obFormChild As New FormChild
6
7
Private Sub FormParent_Load()Sub FormParent_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
8
9
obFormChild.Show()
10
11
obFormChild.setParam(Me)
12
13
End Sub
14
15
Public Function DoAction()Function DoAction() As Boolean
16
17
'添加动作内容
18
19
End Function
20
21
End Class
22
23
Public Class FormChildClass FormChild
24
25
Inherits System.Windows.Forms.Form
26
27
Private obFormParent As FormParent
28
29
Public Sub setParam()Sub setParam(ByRef obFormParam As FormParent)
30
31
Me.obFormParent = obFormParam
32
33
End Sub
34
35
Private Sub Button1_Click()Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
36
37
obFormParent.DoAction()
38
39
End Sub
40
41
End Class
42
2. 将父窗体的控件对象传递给子窗体作为自己的对象。这个方法与1类似,优缺点也相似,但是影响的范围小,同时调用的范围也受限制,只能子窗体只能操作传递过来的对象。

Code2
1
Public Class FormParentClass FormParent
2
3
Inherits System.Windows.Forms.Form
4
5
Dim obFormChild As New FormChild
6
7
Private Sub FormParent_Load()Sub FormParent_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
8
9
obFormChild.Show()
10
11
obFormChild.setParam(Me.Label1)
12
13
End Sub
14
15
End Class
16
17
Public Class FormChildClass FormChild
18
19
Inherits System.Windows.Forms.Form
20
21
Private obControlParent As Label
22
23
Public Sub setParam()Sub setParam(ByRef obControlParam As Label)
24
25
Me.obControlParent = obControlParam
26
27
End Sub
28
29
Private Sub Button1_Click()Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
30
31
obControlParent.Text = "child calls parents"
32
33
End Sub
34
35
End Class
36
3. 将父窗体或父窗体的控件传递给第三方对象,子窗体操作第三方对象。这个方法能够实现显示和逻辑处理的分离,类之间的调用关系虽然复杂了一层,但是线路更加清晰了。需要注意的是,这个时候需要父窗体把一部分传递给逻辑对象,再把逻辑对象也传递给子窗体。举个例子:老爷派一个仆人带着钱给少爷买东西,少爷想买啥,仆人就给买给他。这样,老爷就不用管了,但是仆人的权力就大了。而前面的方法全都是老爷和少爷之间的互动。

Code3
1
Public Class FormParentClass FormParent
2
3
Inherits System.Windows.Forms.Form
4
5
Dim obFormChild As New FormChild
6
7
Dim obLogic As Logic
8
9
Private Sub FormParent_Load()Sub FormParent_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
10
11
obLogic = New Logic(Me.Label1)
12
13
obFormChild.Show()
14
15
obFormChild.setParam(Me.obLogic)
16
17
End Sub
18
19
End Class
20
21
Public Class FormChildClass FormChild
22
23
Inherits System.Windows.Forms.Form
24
25
Private obLogic As Logic
26
27
Public Sub setParam()Sub setParam(ByRef obLogicParam As Logic)
28
29
Me.obLogic = obLogicParam
30
31
End Sub
32
33
Private Sub Button1_Click()Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
34
35
obLogic.DoAction()
36
37
End Sub
38
39
End Class
40
41
Public Class LogicClass Logic
42
43
Private obLabel As Label
44
45
Public Sub New()Sub New(ByRef obLabelParam As Label)
46
47
Me.obLabel = obLabelParam
48
49
End Sub
50
51
Public Sub DoAction()Sub DoAction()
52
53
obLabel.Text = "child calls perent with logic"
54
55
End Sub
56
57
End Class
58
4. 通过第三方逻辑对象进行监控和通信。与3的方法相同部分是需要将逻辑对象传递给子窗体,不同的是需要把父窗体的方法与逻辑类的方法绑定,子窗体通过触发逻辑类的方法来触发父窗体的方法。还是刚才的例子,这次老爷发现仆人吃回扣,于是钱自己管,少爷想买什么,就让仆人告诉老爷,老爷自己买好了给少爷。此方法的好处就是父窗体只需要逻辑类做一个中间的通信兵,动作实现还是自己做,保持了类的封闭性。这个方法是同事提供的,我理解的还不是很深,大体结构如此。

Code4
1
Public Class FormParentClass FormParent
2
3
Inherits System.Windows.Forms.Form
4
5
Dim obFormChild As New FormChild
6
7
Dim obLogic As New Logic
8
9
Private Sub FormParent_Load()Sub FormParent_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
10
11
'定義事件
12
13
AddHandler obLogic.PassInf4Parent, AddressOf DoAction
14
15
obFormChild.setParam(obLogic)
16
17
obFormChild.Show()
18
19
End Sub
20
21
Private Sub DoAction()Sub DoAction()
22
23
'添加事件内容
24
25
Me.Label1.Text = "child calls parents by evnet"
26
27
End Sub
28
29
End Class
30
31
Public Class FormChildClass FormChild
32
33
Inherits System.Windows.Forms.Form
34
35
Private obLogic As Logic
36
37
Public Sub setParam()Sub setParam(ByRef obLogicParam As Logic)
38
39
Me.obLogic = obLogicParam
40
41
End Sub
42
43
Private Sub Button1_Click()Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
44
45
obLogic.PassInf4Child()
46
47
End Sub
48
49
End Class
50
51
Public Class LogicClass Logic
52
53
Public Delegate Sub PassInf4Own()Sub PassInf4Own()
54
55
Public Event PassInf4Parent As PassInf4Own
56
57
Public Function PassInf4Child()Function PassInf4Child() As Boolean
58
59
RaiseEvent PassInf4Parent()
60
61
End Function
62
63
End Class
64
在4这个方法的基础上,我们想实现同一个父窗体下多个子窗体之间的调用和控制就方便多了,因为具体动作都是父窗体来实现的,子窗体只需要通过逻辑类传递一个消息就行了。比如说二少爷想让大少爷给他好吃的,大少爷不肯,那么二少爷和仆人都没辙,毕竟他们没有这个权力调动大少爷。但是二少爷让仆人告诉老爷,这事就好办了,老爷自然会让大少爷把东西给他弟弟并批评他:“你怎么不让着弟弟。”呵呵。
这都是比较简单的方法,是目前笔者所掌握的。有什么更好的方法,欢迎大家交流。