工程中总共介绍了三种方法:
###方法1:通过保存对象的引用调用其方法实现对子窗体的控制;
###方法2:通过委托,在子窗体显示之前,为委托赋值,关注主窗体的数据变化,当有当有多个窗体需要接收信息,只需要为委托继续赋值(+=)即可,实现了数据传递的解耦性;
###方法3:子窗体弹出来之前,注册事件,关注主窗体消息的变化,当有多个窗体需要接收信息,,只需要分别为窗体注册数据接收事件即可,实现了数据传递的解耦性;
方法2与方法3即为发布订阅模式(观察者模式)----我也是设计模式的初学者,如有问题欢迎大家email我,谢谢;
演示窗体的界面如下:
在MainForm中打开A、B窗体,在MainForm中输入文本数据,点击发送消息,A、B的文本框会显示对应的数据;
主窗体为消息的发布者,窗体A、B等等为消息的接收者;
部分代码如下(全部源代码参考上述链接):
1、主窗体的部分代码:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace WinFrmDemo 12 { 13 14 15 public partial class MainForm : Form 16 { 17 #region 方法1(不推荐)--通过保存对象的引用调用的对象的公有方法实现窗体的传值 18 //当接收数据的窗体增加,需要修改发送消息的代码,并且增加相应数量的窗体引用 可扩展性差,耦合性较高 19 //public ObeserverFormA ChildFormA { get; set; } 20 //public ObeserverFormB ChildFormB { get; set; } 21 #endregion 22 23 #region 方法2---委托方式传值 24 //定义发布消息的委托 委托是一个类型 委托可以在外部获得执行 25 public Action<string> SendMsg { get; set; } 26 #endregion 27 28 #region 方法3(推荐)--事件方式 29 //增加event关键字 30 //定 义消息发布的事件 事件是委托的一个特殊实例 事件只能在类的内部触发执行 31 public event EventHandler SendMsgEvent; //使用默认的事件处理委托 32 #endregion 33 34 35 36 public MainForm() 37 { 38 InitializeComponent(); 39 } 40 41 private void ParentFrm_Load(object sender, EventArgs e) 42 { 43 44 #region 方法1(不推荐) 45 //ObeserverFormA childFormA = new ObeserverFormA(); 46 //ChildFormA = childFormA; 47 //childFormA.Show(); 48 //ObeserverFormB childFormB = new ObeserverFormB(); 49 //ChildFormB = childFormB; 50 //childFormB.Show(); 51 #endregion 52 53 #region 方法2---委托方式传值 54 //子窗体弹出来之前,为委托赋值,关注主窗体消息的变化,当有多个窗体需要接收信息,只需要在此修改即可 55 //ObeserverFormA childFormA = new ObeserverFormA(); 56 //SendMsg += childFormA.SetText;//委托赋值 57 //childFormA.Show(); 58 //ObeserverFormB childFormB = new ObeserverFormB(); 59 //SendMsg += childFormB.SetText; 60 //childFormB.Show(); 61 #endregion 62 63 64 #region 方法3(推荐)--事件方式 65 //子窗体弹出来之前,注册事件,关注主窗体消息的变化,当有多个窗体需要接收信息,只需要在此修改即可 66 ObeserverFormA childFormA = new ObeserverFormA(); 67 SendMsgEvent += childFormA.MainFormTxtChaned;//为子窗体注册事件,在子窗体中事件处理代码中设置文本 68 childFormA.Show(); 69 ObeserverFormB childFormB = new ObeserverFormB(); 70 SendMsgEvent += childFormB.MainFormTxtChaned; 71 childFormB.Show(); 72 #endregion 73 74 75 76 } 77 78 //当MainForm中输入文本,点击发送消息,子窗体的文本框显示主窗体的数据 79 private void btnSendMsg_Click(object sender, EventArgs e) 80 { 81 #region 方法1(不推荐) 82 83 //ChildFormA.SetText(this.txtMsg.Text); 84 //ChildFormB.SetText(this.txtMsg.Text); 85 86 #endregion 87 88 #region 方法2---委托方式传值 89 //if (SendMsg!=null) 90 //{ 91 // SendMsg(this.txtMsg.Text);//执行所有注册的委托 92 //} 93 94 #endregion 95 96 #region 方法3(推荐)--事件方式 97 //触发事件 98 //EventArgs,写一个子类继承该类,子类中添加需要封装的数据信息,此处只需要传递string信息,详见MyEventArgs 99 SendMsgEvent(this,new MyEventArg(){Text=this.txtMsg.Text}); 100 #endregion 101 } 102 } 103 }
2、子窗体A部分代码
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace WinFrmDemo 12 { 13 public partial class ObeserverFormA : Form 14 { 15 /// <summary> 16 /// 提供外部访问自己元素的方法 17 /// </summary> 18 /// <param name="txt"></param> 19 public void SetText(string txt) 20 { 21 this.txtMsg.Text = txt; 22 } 23 public ObeserverFormA() 24 { 25 InitializeComponent(); 26 } 27 28 public void AfterParentFrmTextChange(object sender, EventArgs e) 29 { 30 //拿到父窗体的传来的文本 31 MyEventArg arg = e as MyEventArg; 32 this.SetText(arg.Text); 33 } 34 35 internal void MainFormTxtChaned(object sender, EventArgs e) 36 { 37 //取到主窗体的传来的文本 38 MyEventArg arg = e as MyEventArg; 39 this.SetText(arg.Text); 40 41 } 42 } 43 }
3、子窗体B的部分代码
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace WinFrmDemo 12 { 13 public partial class ObeserverFormB : Form 14 { 15 16 public ObeserverFormB() 17 { 18 InitializeComponent(); 19 } 20 21 /// <summary> 22 /// 提供外部访问自己元素的方法 23 /// </summary> 24 /// <param name="txt"></param> 25 public void SetText(string txt) 26 { 27 this.txtMsg.Text = txt; 28 } 29 30 internal void MainFormTxtChaned(object sender, EventArgs e) 31 { 32 //取到主窗体的传来的文本 33 MyEventArg arg = e as MyEventArg; 34 this.SetText(arg.Text); 35 } 36 } 37 }
所有的道理都是相通的,我们所做的并非是创造性的工作,所有的问题前人都曾经解决,所以我们更是无所畏惧,更何况我们不只有书店,而且有互联网,动动手脚就能找到需要的资料,我们只要认真研究就够了。所以当遇到困难时,请静下心来慢慢研究,因为只要用心,没有学不会的东西。
补充:
在和窗体同一个项目中定义的MyEventArgs.cs文件
文件内容如下
************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WinFrmDemo
{
public class MyEventArg :EventArgs
{
//传递主窗体的数据信息
public string Text { get; set; }
}
}
************
文件内容如下
************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WinFrmDemo
{
public class MyEventArg :EventArgs
{
//传递主窗体的数据信息
public string Text { get; set; }
}
}
************
本文转载自:https://www.cnblogs.com/codeToUp/p/5371062.html