C# winform窗體間傳值(使用委托或事件)


窗體間傳值

今天得空,剛好看到網上好多人再找winform窗體間傳值的問題,由於昨天項目的優化的感覺不錯,就寫了個C# winform窗體間傳值的demo,希望能給需要的人的帶來幫助;

工程的源代碼地址:https://github.com/yes-or-no/WinFormTransValueDemoByDelOrEvent.git

C#winform窗體間傳值,三種方法示例,注釋詳細。使用方法:使用vs2013打開編譯運行即可;

工程中總共介紹了三種方法:
###方法1:通過保存對象的引用調用其方法實現對子窗體的控制;
###方法2:通過委托,在子窗體顯示之前,為委托賦值,關注主窗體的數據變化,當有當有多個窗體需要接收信息,只需要為委托繼續賦值(+=)即可,實現了數據傳遞的解耦性;
###方法3:子窗體彈出來之前,注冊事件,關注主窗體消息的變化,當有多個窗體需要接收信息,,只需要分別為窗體注冊數據接收事件即可,實現了數據傳遞的解耦性;

方法2與方法3即為發布訂閱模式(觀察者模式)----我也是設計模式的初學者,如有問題歡迎大家email我,謝謝;

演示窗體的界面如下:

在MainForm中打開A、B窗體,在MainForm中輸入文本數據,點擊發送消息,A、B的文本框會顯示對應的數據;

主窗體為消息的發布者,窗體A、B等等為消息的接收者;

部分代碼如下(全部源代碼參考上述鏈接):

1、主窗體的部分代碼:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WinFrmDemo
{
    

    public partial class MainForm : Form
    {
        #region 方法1(不推薦)--通過保存對象的引用調用的對象的公有方法實現窗體的傳值
        //當接收數據的窗體增加,需要修改發送消息的代碼,並且增加相應數量的窗體引用  可擴展性差,耦合性較高
        //public ObeserverFormA ChildFormA { get; set; }
        //public ObeserverFormB ChildFormB { get; set; } 
        #endregion

        #region 方法2---委托方式傳值
        //定義發布消息的委托  委托是一個類型 委托可以在外部獲得執行
        public Action<string> SendMsg { get; set; } 
        #endregion

        #region 方法3(推薦)--事件方式
        //增加event關鍵字
        //定 義消息發布的事件  事件是委托的一個特殊實例  事件只能在類的內部觸發執行
        public event EventHandler SendMsgEvent; //使用默認的事件處理委托
        #endregion


       
        public MainForm()
        {
            InitializeComponent();
        }

        private void ParentFrm_Load(object sender, EventArgs e)
        {

            #region 方法1(不推薦)
            //ObeserverFormA childFormA = new ObeserverFormA();
            //ChildFormA = childFormA;
            //childFormA.Show();
            //ObeserverFormB childFormB = new ObeserverFormB();
            //ChildFormB = childFormB;
            //childFormB.Show(); 
            #endregion

            #region 方法2---委托方式傳值
            //子窗體彈出來之前,為委托賦值,關注主窗體消息的變化,當有多個窗體需要接收信息,只需要在此修改即可
            //ObeserverFormA childFormA = new ObeserverFormA();
            //SendMsg += childFormA.SetText;//委托賦值
            //childFormA.Show();
            //ObeserverFormB childFormB = new ObeserverFormB();
            //SendMsg += childFormB.SetText;
            //childFormB.Show(); 
            #endregion


            #region 方法3(推薦)--事件方式
            //子窗體彈出來之前,注冊事件,關注主窗體消息的變化,當有多個窗體需要接收信息,只需要在此修改即可
            ObeserverFormA childFormA = new ObeserverFormA();
            SendMsgEvent += childFormA.MainFormTxtChaned;//為子窗體注冊事件,在子窗體中事件處理代碼中設置文本
            childFormA.Show();
            ObeserverFormB childFormB = new ObeserverFormB();
            SendMsgEvent += childFormB.MainFormTxtChaned;
            childFormB.Show();
            #endregion


            
        }

        //當MainForm中輸入文本,點擊發送消息,子窗體的文本框顯示主窗體的數據
        private void btnSendMsg_Click(object sender, EventArgs e)
        {
            #region 方法1(不推薦)

            //ChildFormA.SetText(this.txtMsg.Text);
            //ChildFormB.SetText(this.txtMsg.Text); 

            #endregion

            #region 方法2---委托方式傳值
            //if (SendMsg!=null)
            //{
            //    SendMsg(this.txtMsg.Text);//執行所有注冊的委托
            //}

            #endregion

            #region 方法3(推薦)--事件方式
            //觸發事件
            //EventArgs,寫一個子類繼承該類,子類中添加需要封裝的數據信息,此處只需要傳遞string信息,詳見MyEventArgs
            SendMsgEvent(this,new MyEventArg(){Text=this.txtMsg.Text});
            #endregion
        }
    }
}

2、子窗體A部分代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WinFrmDemo
{
    public partial class ObeserverFormA : Form
    {
        /// <summary>
        /// 提供外部訪問自己元素的方法
        /// </summary>
        /// <param name="txt"></param>
        public void SetText(string txt)
        {
            this.txtMsg.Text = txt;
        }
        public ObeserverFormA()
        {
            InitializeComponent();
        }

        public void AfterParentFrmTextChange(object sender, EventArgs e)
        {
            //拿到父窗體的傳來的文本
            MyEventArg arg = e as MyEventArg;
            this.SetText(arg.Text);
        }

        internal void MainFormTxtChaned(object sender, EventArgs e)
        {
            //取到主窗體的傳來的文本
            MyEventArg arg = e as MyEventArg;
            this.SetText(arg.Text);
            
        }
    }
}

3、子窗體B的部分代碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WinFrmDemo
{
    public partial class ObeserverFormB : Form
    {

        public ObeserverFormB()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 提供外部訪問自己元素的方法
        /// </summary>
        /// <param name="txt"></param>
        public void SetText(string txt)
        {
            this.txtMsg.Text = txt;
        }

        internal void MainFormTxtChaned(object sender, EventArgs e)
        {
            //取到主窗體的傳來的文本
            MyEventArg arg = e as MyEventArg;
            this.SetText(arg.Text);
        }
    }
}

 

 

來源:http://www.cnblogs.com/codeToUp/p/5371062.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM