C# 利用委托 父子窗口数据传递

## 参考链接

WinForm中利用委托和事件实现子窗体传值给父窗体_winform子窗体向父窗体传值-CSDN博客

C#跨窗体传值的几种方法分析(很详细) - xh6300 - 博客园 (cnblogs.com)

 

## Form1 父窗口

// .Net8 Winform
using static WinFormsApp6.Form2;

namespace WinFormsApp6
{
    // Form1 代码

    // 说明: 该方法是用委托来传入和接受方法参数, 委托一般定义在子窗口.
    // 该方法有四个控件
    // textBox1 用于传送值给Form2.textBox1,
    // textBox2 用于接受Form2.textBox2的值. 
    // button1 传送textBox1 值给Form2.textBox1,
    // button2 打开Form2窗口, 并接受来自Form2.Sender_ToForm1的方法参数值


    public partial class Form1 : Form
    {

        Form2 form2;  // 实例化窗口2(Form2), 用于调用Form2的方法;
        Form2.Weituo? weituo;       // 定义一个委托变量weituo, 这个变量用于传送主窗口内一个带参数的方法.  这个委托是来自子窗口(Form2)的委托;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)       // 载入窗口执行的任务
        {
            button1.Enabled = false;
        }

        void Accept_Form2(string xx)  // 接受窗口2 传入到窗口1
        {
            textBox2.Text = xx;              // xx变量接收来自Form2内的委托
        }

        void sync_Form2(string xx)  // 用于同步Form2.textBox3
        {
            textBox3.Text = xx;              // xx变量接收来自Form2内的委托
        }


        void Sender_ToForm2(string xx)  // 将参数传入到窗口2
        {
            form2.Accept_Form1(xx);                   // 读取Form2的方法, xx参数等于Form2的方法参数, 类似于Accept_Form2
        }

        private void button1_Click(object sender, EventArgs e)      // 实例化委托并传入值到Form2
        {
            weituo = new(Sender_ToForm2);           // weituo并没有实例化, 实例化委托后并填入执行
                                                    // Weituo weituo = new(Sender_ToForm2)          // 如果不在类中新建委托变量, 也可以直接在方法内实例化委托 ; 
            weituo(textBox1.Text);                           // 执行委托;  用textBox1.Text的值给到Sender_ToForm2的参数, 然后执行Sender_ToForm2.   相当于 Sender_ToForm2(textBox1.Text)
        }

        private void button2_Click(object sender, EventArgs e)      // 实例化Form2的weituo2委托.
        {
            form2 = new();                                                      // 当该作用域结束, 则实例化对象也被销毁.
            button1.Enabled = true;                                     //  Sender_ToForm2方法调用了form2, 但是form2没有被实例化, 所以需要先禁用, 待实例化后再启用
            form2.weituo2 = new(Accept_Form2);              //  实例化Form2的weituo2委托, weituo2 是在 Form2 的Weituo变量.
            form2.weituo3 = new(sync_Form2);
            form2.Show();                                                   //   显示Form2窗口.  不要使用ShowDialog(), 这样Form1无法使用.

        }

        private void textBox3_TextChanged(object sender, EventArgs e)   // 编辑框被编辑事件.
        {

            form2.sync_TextBox(textBox3.Text);               // 找到Form2的方法
        }



        // 至此Form1 的代码写完.
        // 你需要定义两个带参数的方法, 一个用于接受参数值,  一个用于传送参数值,
        // 实例化两个委托, 也是一个用于接受参数值, 一个用于传送参数值.
    }

}

 

## Form2 子窗口

// .Net8 Winform
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;
using static System.Windows.Forms.DataFormats;

namespace WinFormsApp6
{

    // Form2 代码
    // 该方法有三个控件
    // textBox1.Text 用于接受来自Form1.textBox1.Text的值
    // textBox2.Text 传送到 Form1.textBox2.Text 值 
    // button1 发送 Form2.textBox2.Text值到Form1.textBox2.Text 

    public partial class Form2 : Form
    {

        public delegate void Weituo(string x);   // 定义一个带参数的委托, 这个参数是用于传值的
        public Weituo? weituo2;                          // 新建一个公开的委托变量,  这个委托变量是给到Form1来传参的.
        public Weituo? weituo3;


        public Form2()
        {
            InitializeComponent();
        }


        public void Accept_Form1(string x)        // 该方法用于给到Form1的方法调用, 所以需要设置为公开.
        {
            textBox1.Text = x;                                    // 该方法的参数值 x 是来自Form1的 Sender_ToForm2方法参数值                 
        }


        public string sync_TextBox(string x)        // 该方法用于给到Form1的方法调用, 所以需要设置为公开.
        {
            return textBox3.Text =x;                                    // 该方法的参数值 x 是来自Form1的 Sender_ToForm2方法参数值                 
        }

        private void button1_Click(object sender, EventArgs e)  // 
        {
            if (weituo2 != null)                 // 判断weituo2是否实例化.
            {
                weituo2(textBox2.Text);         // 将textBox2.Text的值给到weituo2内的方法.
            }
        }

        private void textBox3_TextChanged(object sender, EventArgs e)   // 编辑框被编辑事件. 如果需要访问Form1的控件属性值还是需要利用委托.
        {
            if (weituo3 != null)                 // 判断weituo2是否实例化.
            {
                weituo3(textBox3.Text);         // 将textBox2.Text的值给到weituo2内的方法.
            }
        }
        
         private void Form2_FormClosed(object sender, FormClosedEventArgs e) // 窗口关闭结束资源
        {
            this.Dispose();
        }
    }

    // Form2 需要定义一个委托, 不需要在Form2内实例化委托, 因为在Form1.button2中已经实例化委托,  然后再新建一个方法来传参.
    // 虽然可以在Form2实例化委托, 但是委托无法调用Form1的方法(就算能够调用也是静态方法, 而控件不是静态类型, 这样会有冲突),
    // 如果在Form2中实例化Form1, 相当于Form2的子窗口 如: Form1.Form2.Form1, 这样原来Form1窗口是不会接受参数值的.
    //
    // 总结下来, 委托是在子窗口定义的, 需要实例化委托两次, 一次用于传参, 一次用于接受参数(应该是Form2的传参),
    // 共建立三个带参数的方法用于委托传参, 梳理一下
    // 符号说明 < : 接受参数,   > : 传送参数.
    // Form1.Accept_Form2 < Form2.button1
    // Form1.Sender_ToForm2(btton1) > From2.Accept_Form1
    //
    // 定义流程
    // 1. 先在Form2 定义一个带参数委托, 然后在Form2类中 在新建一个委托变量
    // 2. 回到Form1 中定义两个带参数的方法, 一个用于传送参数值, 一个用于接受参数值.
    // 3. 然后在Form1 在执行方法中实例化委托,  实例化委托需要填入参数. 因为有两个方法所以也需要实例化两个委托处理两个方法.  
    // 需要注意的是在Form2中不能实例化Form1, 因为无法调用Form1的方法,  所以之前在Form2 新建的委托变量, 就是用在Form1执行方法中调用,
    // 执行方法填入Form2.Show(), 实例化的委托和Show方法都包含在该执行方法中, 这样就不需要在Form2中实例化Form1了.
    // 4. Form1需要传入参数值到Form2中, 但是不能直接调用Form2的控件, 所以需要新建一个公开的方法来接受Form1方法的参数值.
    // 5. 由于Form2窗口是Form1执行方法调用的, 所以还是属于Form1执行方法的作用域内, 在Form1的执行方法中实例化委托, 并且绑定了方法,
    // 所以直接在Form2的执行方法中直接调用已被实例化的委托变量即可, 调用该委托变量还需要填入参数值.   在委托被实例化的时候就需要绑定方法.
    // 至此就完成了, 需要加强理解委托和方法作用域.
}

 

## 执行过程

 

posted @ 2024-03-24 09:14  edolf  阅读(245)  评论(0编辑  收藏  举报