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(); } }

浙公网安备 33010602011771号