【轉】C# winform窗體間傳值(使用委託或事件)
阿新 • • 發佈:2020-11-15
工程中總共介紹了三種方法:
###方法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 }