Winform窗体间相互访问的几种实现方法

窗体组合经常会使用到,但是要避免循环引用的问题。
窗体对象相互引用的可以使用单例模式,用窗体类静态方法获取实例对象再去调用具体内容。在窗体间相互引用时,使用单例可以解决循环引用问题。

窗体间的数据传递可以使用委托和事件

委托与事件的区别:个人乱扯
委托是类;事件是一种委托类型,提供发布和订阅机制。
委托由定义者注册和注销和执行;事件由定义者触发,提供调用者注册和注销
委托使用Func<> 和 Action<> 可以满足丰富的委托类型,注册委托的函数需要满足委托函数签名,可实现同步,异步且能带回调执行委托
事件直接用EventArgs,或EventArgs继承自定义事件类丰富事件属性;注册事件函数需要提过(object sender, MsgEventArgs e)参数

使用单例

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 WindowsFormsApp2
{
    public partial class Form2 : Form
    {
        //窗体组合经常会使用到,但是要避免循环引用的问题。
        //窗体对象相互引用的可以使用单例模式,用窗体类静态方法获取实例对象再去调用具体内容。在窗体间相互引用时,使用单例可以解决循环引用问题。

        public TextBox TextBox1
        {
            get
            {
                return this.textBox1;
            }
            set
            {
                this.textBox1 = value;
            }

        }
        //在Form2中添加Form3实例引用,组合
        private static readonly Form3 form3 = Form3.GetForm3();


        //Form2实例单例
        private static readonly Form2 form2 = new Form2();

        private Form2()
        {
            InitializeComponent();
        }

        //获取Form2单例实例
        public static Form2 GetForm2()
        {
            return form2;
        }


        private void Form2_Load(object sender, EventArgs e)
        {
            banding(form3, panel1);
        }

        private void banding(Form form, Panel panel)
        {
            panel.Controls.Clear();
            form.FormBorderStyle = FormBorderStyle.None;
            form.StartPosition = FormStartPosition.Manual;
            //form.Size = page.Size;
            form.Dock = DockStyle.Fill;
            form.TopLevel = false;
            panel.Controls.Add(form);
            form.Show();
        }


        private void button1_Click(object sender, EventArgs e)
        {
            //在Form2中通过form3引用修改Form3内容
            form3.TextBox1.Text = "123";
        }
        private void button2_Click(object sender, EventArgs e)
        {
        }

        private void button3_Click(object sender, EventArgs e)
        {
            Form4 form4 = new Form4();
            form4.Show();
        }
    }
}

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 WindowsFormsApp2
{
    public partial class Form3 : Form
    {
        public TextBox TextBox1
        {
            get
            {
                return this.textBox1;
            }
            set
            {
                this.textBox1 = value;
            }

        }

        //Form3实例单例
        private static readonly Form3 form3 = new Form3();
        private Form3()
        {
            InitializeComponent();
        }

        public static Form3 GetForm3()
        {
            return form3;
        }


        private void button1_Click(object sender, EventArgs e)
        {
            //因为Form2已经组合了Form3,想要通过Form3中修改Form2内容,不应该在Form3中组合Form2,会导致循环引用
            //应该在Form3中直接调用Form2获取对象引用的静态方法去调用具体内容
            //在窗体间相互引用时,使用单例可以解决循环引用问题
            Form2.GetForm2().TextBox1.Text = "456";
        }

        private void button2_Click(object sender, EventArgs e)
        {

        }

        private void Form3_Load(object sender, EventArgs e)
        {

        }
    }
}

使用委托和事件

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowsFormsApp2
{
    public class MsgEventArgs : EventArgs//自定义事件类;无参数时可以直接用EventArgs
    {
        public string Msg { get; private set; }
        public MsgEventArgs(string msg)
        {
            this.Msg = msg;
        }
    }
}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    //窗体间的数据传递可以使用委托和事件

    public partial class Form4 : Form
    {
        //定义委托
        public Action<string> SendMsg { get; set; }

        public Form4()
        {
            InitializeComponent();
        }

        private void Form4_Load(object sender, EventArgs e)
        {
            Form5 form5 = new Form5();         
            SendMsg += form5.SetText;//绑定委托;但委托被执行时,绑定委托的函数将被执行;可同步,异步且能带回调执行委托

            form5.MsgInfoEvent += BingEvent;//订阅事件;但事件被触发时,订阅事件的函数将被调用

            //委托与事件的区别:个人乱扯
            //委托由定义者注册和注销和执行;事件由定义者触发,提供调用者注册和注销
            //委托使用Func<> 和 Action<> 可以满足丰富的委托类型,注册委托的函数需要满足委托函数签名,可实现同步,异步且能带回调执行委托
            //事件直接用EventArgs,或EventArgs继承自定义事件类丰富事件属性;注册事件函数需要提过(object sender, MsgEventArgs e)参数


            banding(form5, panel1);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //执行委托
            //if (SendMsg != null)
            //{
            //    //执行委托,向form5传值
            //    SendMsg(this.textBox1.Text);
            //}  

            //同步执行委托;阻塞
            Debug.WriteLine("button1_Click begin");
            //SendMsg.Invoke(this.textBox1.Text);

            //异步执行委托;非阻塞
            //需要在程序入口添加 Control.CheckForIllegalCrossThreadCalls = false; //设置不捕获线程异常 
            //解决“线程间操作无效: 从不是创建控件“xxxx”的线程访问它。”
            //SendMsg.BeginInvoke(this.textBox1.Text,null,null);
            SendMsg.BeginInvoke(this.textBox1.Text, Callback, null);//异步执行委托,委托函数执行完成后再执行回调函数Callback

            Debug.WriteLine("button1_Click end");
        }

        //SendMsg回调函数
        public void Callback(IAsyncResult iar)
        {
            //获取绑定委托函数的引用
            AsyncResult ar = (AsyncResult)iar;
            Action<string> del = (Action<string>)ar.AsyncDelegate;
            del.EndInvoke(iar);//等待委托函数执行完成
            Debug.WriteLine("Callback end");
        }

        //订阅事件函数
        private void BingEvent(object sender, MsgEventArgs e)
        {
            this.textBox1.Text = e.Msg;
        }

        private void banding(Form form, Panel panel)
        {
            panel.Controls.Clear();
            form.FormBorderStyle = FormBorderStyle.None;
            form.StartPosition = FormStartPosition.Manual;
            //form.Size = page.Size;
            form.Dock = DockStyle.Fill;
            form.TopLevel = false;
            panel.Controls.Add(form);
            form.Show();
        }


    }
}

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 WindowsFormsApp2
{
    public partial class Form5 : Form
    {

        public event EventHandler<MsgEventArgs> MsgInfoEvent;//类中声明事件;发布事件;提供外部订阅+=和注销-=
        public Form5()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //触发事件,外部订阅事件的函数将被执行
            EventHandler<MsgEventArgs> msgInfo = MsgInfoEvent;
            if (msgInfo != null)
            {
                msgInfo(this, new MsgEventArgs(this.textBox1.Text));
            }
        }
        public void SetText(string msg)
        {
            System.Threading.Thread.Sleep(3000);
            this.textBox1.Text = msg;
        }
    }

}

测试代码链接

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值