• 【WinForm】—窗体之间传值的几种方式


    前言

        小编最近维护一个Winfrom窗体,是项目中CS端的主窗体,很多子窗体需要从主窗体获取值,同时子窗体还需要给主窗体回传值,下面来给大家介绍一下。

    正文

        本文中以主窗体为frmMain,子窗体为frmGroup ,两窗体之间的传值来做示例。

    方式一: 使用公共静态变量传值

    主窗体frmMain中代码

    public partial class frmMain : Form
    {
     //声明工位ID 为公共静态变量
     public static string terminalID = "";
     //给静态变量赋值
     terminalID = "q13bh01-bh12";
     }

    子窗体frmGroup中代码

     private void frmGroup_Load(object sender, EventArgs e)
    {
        this.txtTerminalID.Text= frmMain.terminalID.Trim(); 
        //可以再赋值给静态成员,方便其他窗体调用
        frmMain.terminalID = "q13bh01-bh11";
    }

    特点 : 双向传值,实现简单 
    缺点: 静态变量在类加载的时候分配内存,存储于方法区,一般不会被销毁,在系统不够内存情况下会自动回收静态内存,这样就会引起访问全局静态错误。

    方式二: 使用公共变量传值

    主窗体frmMain中代码

    public partial class frmMain : Form
    {
     //声明工位ID 为公共变量
     public string terminalID = "";
     //给变量赋值
     terminalID = "q13bh01-bh12";
     //单击‘行为’按钮的时候会给窗体传值
      private void btnGroup_Click(object sender, EventArgs e)
            {
                frmGroup frmGro = new  frmGroup();
                //变量传值 ,注意顺序写在ShowDialog()方法之前
                frmGro .stationID = this.terminalID;
                frmGro .ShowDialog();
            }
     }

    子窗体frmGroup中代码

      public partial class frmGroup : Form
      {
        //定义公共属性
        public string stationID = "";
      }

    特点 : 单向传值,只能主窗体给子窗体传值,实现简单

    方式三: 使用委托传值

    先来看子窗体frmGroup中代码

    namespace Siemens.Simatic.GUIClient.MESClient
    {
        //1、声明一个委托
        public delegate void setTextValue(string textValue,bool flag);
        public partial class frmGroup : Form
        {
            //2、声明一个委托类型的事件
             public event setTextValue setFormTextValue;
             public string groupName = "";
             public bool flagBtnGroup = false;  
             public frmGroup()
             {
               InitializeComponent();
             }
              //轮询‘行为’按钮(相当于按钮单击事件)
              private void tmrBtn_Tick(object sender, EventArgs e)
              {
                if (sender is ButtonX) {
                    ButtonX butX = (ButtonX)sender;//判断触发事件的是不是Button
                    groupName = butX.Text.Trim();
                    flagBtnGroup = true;
                    //3、准备要回传的数据。  
                    setFormTextValue(this.groupName.Replace(" ", ""), this.flagBtnGroup );
                    this.Close();
                    return;
                } 
            }

    主窗体frmMain中代码

      private void btnGroup_Click(object sender, EventArgs e)
            {
                frmGroup frmGro = new  frmGroup();
                 //4、初始化事件  
                frmGro .setFormTextValue += new setTextValue(frmGro _setFormTextValue);
                //变量传值 ,注意顺序写在ShowDialog()方法之前
                frmGro .stationID = this.terminalID;
                frmGro .ShowDialog();
            }
            //5、事件具体实现
             public void frmGro _setFormTextValue(string textValue,bool flag)
            { 
                this.newGroupName = textValue;
                this.flagBtnGroup = flag;
                if (!string.IsNullOrEmpty(newGroupName))
                {
                     ……
                }
             }
     

    特点 :适合子窗体数据实时回传父窗体。

    叨叨两句

        项目中父窗体向子窗体传值传的是固定值,用的是第一种方式,子窗体向父窗体传值传的是变化的值,用的是第三种方式,第三种方式为我解决了一个大麻烦。

    总结

        感谢您的阅读,窗体传值有好多种方法,构造参数参数传值、公共属性传值等,各种场景下找到适合需求的最好,希望为小编提出宝贵意见!

    1. 登陆逻辑

    • FrmMain 为主窗体(启动窗体)
    • FrmLogin 为登陆窗体

    在“主窗体”中使用ShowDialog()方法显示“登陆窗体”,并通过“登陆窗体”的DialogResult告知“主窗体”是否登陆成功。

    1.1 主窗体:

    private void FrmMain_Load(object sender, EventArgs e)
    {
        FrmLogin frm = new FrmLogin();
        if (frm.ShowDialog() == DialogResult.OK)
        {
            // 执行主窗体的一些初始化内容
        }
        else
        {
            this.Close();    // 关闭主窗体
        }
    }

    1.2 登陆窗体:

    private vode btn_Login_Click(object sender, EventArgs e)
    {
        this.DialogResult = DialogResult.OK;
    }

    2. 窗体间的数据传递

    “登陆窗体”在执行完毕后,需要将登陆用的信息传递给“主窗体”,其传递的过程就是“暂时”将用户信息存在“主窗体”可以获取的“地方”,根据“地方”不同可以有一下几种方案。

    新建 User.cs

    public class User {
        public string username;
        public User(string username)
        {
            this.username = username;
        }
    }

    2.1 将数据暂存在“登陆窗体”的Tag属性上

    2.1.1 登陆窗体:

    private vode btn_Login_Click(object sender, EventArgs e)
    {
        this.Tag = new User('rianman');
        this.DialogResult = DialogResult.OK;
    }

    2.1.2 主窗体:

    private void FrmMain_Load(object sender, EventArgs e)
    {
        FrmLogin frm = new FrmLogin();
        if (frm.ShowDialog() == DialogResult.OK)
        {
            User user = frm.Tag as User;    // 此处获取“登陆窗体”传递过来的数据
        }
        else
        {
            this.Close();    // 关闭主窗体
        }
    }

    2.2 将数据暂存在“主窗体”的Tag属性上

    2.2.1 登陆窗体:

    private vode btn_Login_Click(object sender, EventArgs e)
    {
        FrmMain main this.Owner as FrmMain;
        main.Tag = new User("rainman");
        this.DialogResult = DialogResult.OK;
    }

    2.2.2 主窗体:

    private void FrmMain_Load(object sender, EventArgs e)
    {
        FrmLogin frm = new FrmLogin();
        if (frm.ShowDialog() == DialogResult.OK)
        {
            User user = this.Tag as User;    // 此处获取“登陆窗体”传递过来的数据
        }
        else
        {
            this.Close();    // 关闭主窗体
        }
    }

    2.3 将数据暂存在类的“静态成员”上

    2.3.1 新建Context.cs

    public class Context
    {
        public static User LoginUser = null;
    }

    2.3.2 登陆窗体:

    private vode btn_Login_Click(object sender, EventArgs e)
    {
        Context.LoginUser = user;
        this.DialogResult = DialogResult.OK;
    }

    2.3.3 主窗体:

    private void FrmMain_Load(object sender, EventArgs e)
    {
        FrmLogin frm = new FrmLogin();
        if (frm.ShowDialog() == DialogResult.OK)
        {
            User user = Context.LoginUser;    // 此处获取“登陆窗体”传递过来的数据
        }
        else
        {
            this.Close();    // 关闭主窗体
        }
    }

    2.4 将数据暂存在“主窗体”的特定属性上

    2.4.1 登陆窗体:

    private vode btn_Login_Click(object sender, EventArgs e)
    {
        FrmMain main = this.Owner as FrmMain;
        main.LoginUser = new User("rainman");
        this.DialogResult = DialogResult.OK;
    }

    2.4.2 主窗体:

    public user LoginUser { get; set; }
     
    private void FrmMain_Load(object sender, EventArgs e)
    {
        FrmLogin frm = new FrmLogin();
        if (frm.ShowDialog() == DialogResult.OK)
        {
            User user = this.LoginUser;    // 此处获取“登陆窗体”传递过来的数据
        }
        else
        {
            this.Close();    // 关闭主窗体
        }
    }

    三-----------------------------------------------

    在窗体2中添加如下代码:

     View Code

    在窗体1中添加如下代码:

     View Code

    这种可以实现子窗体和父窗体的相互传值。

    第二种:委托事件传值

    1.在窗体2中命名空间下先定义一个委托:public delegate void ChangeHandleText(string str);//带参数

    2.定义一个事件:public event ChangeHandleText changetext;//定义事件

    3.将事件与委托关联起来:Form2 f=new Form2();  f.changetext+=new ChangeHandleText(Change_text);//关键

    form2代码:

     View Code

    form1代码

     View Code

    第三种:泛型委托和Lambda表达式结合

    简单介绍下Lambda表达式:“Lambda表达式”是一种匿名函数,是一种高效的类似于函数式编程的表达式,Lambda简化了开发中需要编写的代码量。它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型,支持带有可绑定到委托或表达式树的输入参数的内联表达式。所有Lambda表达式都使用Lambda运算符=>,该运算符读作“goes to”。Lambda运算符的左边是输入参数(如果有),右边是表达式或语句块。Lambda表达式x=>x*x读作“x goes  to x times x”。可以将此表达式分配给委托类型。如下图

     View Code

    言归正传。

    窗体2代码

     View Code

    窗体1代码

    复制代码
    public partial class Form1 : Form
     8     {
     9         public Form1()
    10         {
    11             InitializeComponent();
    12         }
    13 
    14         private void button1_Click(object sender, EventArgs e)
    15         {
    16             Form2 f2 = new Form2();
    17             f2.ChangeText = (str) => textBox1.Text = str;//用lambda表达式实现,这句话必须放在f2.ShowDialog();前面
    18             f2.ShowDialog();            
    19         }
    20     }
    复制代码
    public partial class Form1 : Form
     8     {
     9         public Form1()
    10         {
    11             InitializeComponent();
    12         }
    13 
    14         private void button1_Click(object sender, EventArgs e)
    15         {
    16             Form2 f2 = new Form2();
    17             f2.ChangeText = (str) => textBox1.Text = str;//用lambda表达式实现,这句话必须放在f2.ShowDialog();前面
    18             f2.ShowDialog();            
    19         }
    20     }
  • 相关阅读:
    IP寻址方式三
    IP通信基础4
    IP通信基础3
    IP通信基础2
    IP通信基础 1
    IP通信基础
    IP通信原理第二周
    设备选型
    常用virsh命令记录
    [转]enable spice html5 console access in openstack kilo(centos)
  • 原文地址:https://www.cnblogs.com/liuqifeng/p/13403797.html
Copyright © 2020-2023  润新知