Passing data between two Forms in WinForms(一)

是的,WinForm是一项比较老的技术,它没有什么特别吸引人的地方。但是它很有效,而且很快就能建立起新的程序。很多企业仍然有遗留下来的应用程序是用它建立的,其drag-and-drop(拖放)界面的能力也使其在课堂环境中易于使用。

正如其名所示那样,在WinFroms中所做的大部分事情都是围绕Forms进行的,包含创建多个窗体来执行不同的功能。功能包含从用户外收集数据,或显示数据库中的记录供用户编辑。在用户输入所请求的数据,或对记录进行更改,并按下OK按钮关闭当前From后,除非你先对它进行处理,否则所做的更改将会丢失。此时,你可能希望将更改保存到数据库中,但更多情况下,你只是希望将数据传递回那个刚刚创建又关闭的原始Form.

如何在两个Forms之间传递数据?

我看到这个问题被问了很多次,它通常是这些差别不大的问题之一:

  • How do I pass data between two forms?
  • How do I access data from Form1 (or Form2) in Form2 (or Form1)?
  • How do I get the contents of a <TextBox / List / etc> from another form?
  • How do I enter data into a form, and then close it and display it in my first form?

定义工作环境

每个程序是不同的,但是这个特殊的问题有一些实用的、通用的解决方案。让我们先模拟一个问题---这是我看到的非常典型的问题:

有两个Forms,第一个窗体有个按钮用于打开第二个窗体;

第二个窗体收集用户在TextBox控件中输入的数据。当他们运行并关闭时,我需要将这些数据传递回第一个窗体;

下面是我写的代码,但是他们没有按照期望那样工作。我如何将用户输入的内容传递回第一个窗体呢?

 1 public class Form1 : Form
 2 {
 3     public Form1() { }
 4  
 5     private void btnGetUserInput_Click(object sender, EventArgs e)
 6     {
 7         Form2 form2 = new Form2();
 8         form2.ShowDialog();
 9     }
10 }
11  
12 public class Form2 : Form
13 {
14     public Form2() { }
15  
16     private void btnSaveInput_Click(object sender, EventArgs e)
17     {
18         Form1 form1 = new Form1();
19         form1.???  // How do I show my values on the first form?
20         form1.ShowDialog();
21     }
22 }

下面图片是一个非常简单的示例。第一个窗体显示的数据是从第二个窗体收集而来的,可能是在DataGridView或是一些Label。或者也可能是第一个窗体对第二个窗体中的数据执行一些操作,比如保存为一个文件。无论如何,这会是一款非常出色的应用程序。

所以说,我们的模拟环境是:

C#,WinForms

两个窗体,Form1和Form2

Form1随程序启动,包含一个DataGridView和一个可以打开Form2的按钮

Form2有一对TextBox按钮用于接收用户输入,并且有一个按钮用来关闭窗体并保存输入内容

引用原始窗体

一个Form仅仅是另一个类,为了改变任何类的属性,你需要有一个你可以修改的特定实例的引用。

看一下上面btnSaveInput_Click()事件函数中的代码。如果你试图创建一个新的窗体实例用于更新它,那么你就犯了一个关于类如何实例化的工作方式的根本性错误。一个类的多个实例之间不会自动共享数据。

换句话说,当你在Form2内部创建了Form1的第二个实例,它与你刚开始使用的Form1的原始实例没有任何关系。当btnSaveInput_Click()方法结束时,Form1的第二个实例将超出范围,变得不可访问,并且在其中设置的值也不会运用到原始的Form1中。

(你可能会尝试定义可以从任何地方轻松访问的公共静态字段,但是要尽量避免。自然的进程是一个静态类来保存这些静态字段,很快你就有了一个blob(注:一种设计模式),通常被称为god类,这几乎是不可能调试的。)

现在有两种实用的选择用来将得到的数据传递回第一个Form(Form1):

1、仍然在Form2中,将数据推送回Form1。

2、一旦返回到Form1,就从Form2中提取数据。

推送数据到Form1

首先,我会解释如何这样做,然后我会解释为什么不能做。

为了将数据传递回Form1,你需要一个对它的引用。一般来说,这么做最容易的方式是当你实例化Form2时在构造函数中传递一个引用 ,如下所示:

public partial class Form2 : Form
{
    public Form1 form1;
 
    public Form2(Form1 form1)
    {
        InitializeComponent();
        this.form1 = form1;
    }
 
    ...

现在,在第一个Form上,你可以访问公共属性、方法或任何内容。

public partial class Form1 : Form
{
    public Form1() { }
 
    private void btnGetUserInput_Click(object sender, EventArgs e)
    {
       // Notice the 'using' statement. It helps ensure you clean up resources.
       using (var form2 = new Form2(this))
       {
           form2.ShowDialog();
       }
    }
 
    public void SetName(string name)
    {
        lblName.Text = name;
    }
 
    public int Age
    {
        set { lblAge.Text = value.ToString(); }
    }
}
 
public partial class Form2 : Form
{
    private Form1 form1;
 
    public Form2(Form1 form1)
    {
        InitializeComponent();
        this.form1 = form1;
    }
 
    private void btnClose_Click(object sender, EventArgs e)
    {
        form1.SetName(txtName.Text);
 
        int age;
        if (int.TryParse(txtAge.Text, out age))
            form1.Age = age;
 
        this.Close();
    }
}

 

posted @ 2022-08-06 13:28  chenlight  阅读(84)  评论(0)    收藏  举报