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

 

posted @ 2017-08-30 14:14  幽冥狂_七  阅读(12040)  评论(1编辑  收藏  举报