【轉】C# winform窗體間傳值(使用委託或事件)

工程中總共介紹了三種方法:
###方法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; }
}
}

************
 
本文轉載自:https://www.cnblogs.com/codeToUp/p/5371062.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章