# 窗口间的数据传递（一）

> 来源：梦飞idc云平台 | 原文：https://www.mfisp.com/10727.html | 发布：2022-09-29 | 更新：2022-09-29 | 分类：投稿分享

*Windows*窗体是用于*Microsoft Windows*应用程序开发的、基于*.NET Framework*的新平台。此框架提供一个有条理的、面向对象的、可扩展的类集，它使您得以开发丰富的*Windows*应用程序。一个*Windows*窗体就代表了*.NET*架构里的*System.Windows.Forms.Form*类的一个实例。

 

作者在*CSDN*技术论坛*.NET*板块下的*C#*分类经常看到有人问起如何在两个*Form*间传递数据，访问修改对方窗体里面的值。对于有经验的程序员来说不是什么高深的东西，而对于初学者来说这些基础的东西往往是一个问题，并且存在这种现象，往往比较复杂的东西他们会，要用什么了就去学什么，实际上并没有真正的去理解掌握它，基础不扎实，所以就有了想通过自己对窗体编程积累的经验来写一些这方面的文章，以供学*.NET*的朋友参考，也借此机会同各位朋友进行交流，写得不合理的地方请各位朋友提宝贵意见，下面我分了三个部分来讲。

  

一．使用带参数的构造函数

 

我们要做的准备工作就是新建两个窗

 

![窗口间的数据传递（一）](https://www.mfisp.com/wp-content/uploads/2021/10/20220929204054xBBLo1.jpeg)

 

说明：*Form1*为主窗体，包含控件：文本框*textBoxFrm1*，多选框*checkBoxFrm1*和按钮*buttonEdit*；

  

*Form2*为子窗体，包含控件：文本框*textBoxFrm2*，多选框*checkBoxFrm2*和按钮*buttonOK*，*buttonCancel*。

   

当我们新建一个窗体的时候，设计器会生成默认的构造函数：

  

*public Form2()*

  

*{*

  

*InitializeComponent();*

  

*}*

  

它不带参数，既然我们要把*Form1*中的一些数据传到*Form2*中去，为什么不在*Form2*的构造函数里做文章呢？

  

假设我们要实现使*Form2*中的文本框显示*Form1*里*textBoxFrm1*的值，修改子窗体的构造函数：

  

*public Form2(string text)*

  

*{*

  

*InitializeComponent();*

  

*this.textBoxFrm2.Text = text;*

  

*}*

  

增加*Form1*中的修改按钮点击事件，处理函数如下：

  

*private void buttonEdit_Click(object sender, System.EventArgs e)*

  

*{*

  

*Form2 formChild = new Form2(this.textBoxFrm1.Text);*

  

*formChild.Show();*

  

*}*

  

我们把*this.textBoxFrm1.Text*作为参数传到子窗体构造函数，以非模式方式打开，这样打开的*formChild*的文本框就显示了”主窗体”文本，是不是很简单，接下来我们传一个*boolean*数据给子窗体。

  

*Public Form2(string text,bool checkedValue)*

  

*{*

  

*InitializeComponent();*

  

*this.textBoxFrm2.Text = text;*

  

*this.checkBoxFrm2.Checked = checkedValue;*

  

*}*

  

在主窗体中的修改按钮点击处理，我采用了打开模式窗口的方式，其实在这个例子中看不出有什么分别，

  

*private void buttonEdit_Click(object sender, System.EventArgs e)*

  

*{*

  

*Form2 formChild = new Form2(this.textBoxFrm1.Text,this.checkBoxFrm1.Checked);*

  

*formChild.ShowDialog();*

  

*}*

  

结果在预料之中，但是这里明显存在不足，在子窗体里的数据修改后不能传给主窗体，也就是说主窗体不受子窗体的影响。而在实际的开发过程中我们经常使用子窗体来修改主窗体里面的数据，那怎么解决呢？

  

在*.NET*中有两种类型，值类型和引用类型。值类型是从*ValueType*继承而来，而*ValueType*又是从*Object*继承；对于引用类型它直接继承*Object*类型。这下让我们看看怎样通过*Form2*来修改*Form1*里的数据。

  

还是让我们来修改*Form2*的代码。

  

*Private TextBox textBoxFrm12;*

  

*private CheckBox checkBoxFrm12;*

  

*public Form2(TextBox heckbo,CheckBox heckbox)*

  

*{*

  

*InitializeComponent();*

  

*this.textBoxFrm2.Text = heckbo.Text;*

  

*this.checkBoxFrm2.Checked = heckbox.Checked;*

  

*this.textBoxFrm12 = heckbo;*

  

*this.checkBoxFrm12 = heckbox;*

  

*}*

  

现在我们传了两个引用类型的数据：*TextBox*类型，和*CheckBox*；另外在*Form2*中增加了两个类数据成员*textBoxFrm12*、*checkBoxFrm12*用来分别保存构造函数传来的变量，不过他们并不属于*Form2*的*Controls*容器。修改*Form2*的确定按钮点击事件函数：

  

*private void buttonOK_Click(object sender, System.EventArgs e)*

  

*{*

  

*this.textBoxFrm12.Text = this.textBoxFrm2.Text;*

  

*this.checkBoxFrm12.Checked = this.checkBoxFrm2.Checked;*

  

*this.Close();*

  

*}*

  

上面的代码我们通过把*textBoxFrm2*的*Text*和*checkBoxFrm2.Checked*赋给*textBoxFrm12*和*checkBoxFrm12*完成了对主窗体中的*textBoxFrm1*和*checkBoxFrm2*的修改，因为*textBoxFrm1*和*textBoxFrm12*是同一个引用，而*checkBoxFrm2*和*checkBoxFrm12*也是。

  

到这里为止功能是实现了，但是总觉得不是很合理，让两个窗体控件传来传去，现在我举一个恰当一点的例子。

  

修改了两个窗体：

 

![窗口间的数据传递（一）](https://www.mfisp.com/wp-content/uploads/2021/10/20220929205747yakWiW.jpeg)

 

说明：在这个例子中我们的两个窗体都加了一个*ListBox*用来显示*ArrayList*中的内容。

  

主窗体中控件：*listBoxFrm1*，*buttonEdit*；

  

子窗体中控件：*listBoxFrm2*，*textBoxAdd*，*buttonAdd*，*buttonEdit*，*buttonOK*。

  

这次我们用*ArrayList*来作为传递数据，在*Form1*中定义类数据成员：

  

*private ArrayList listData1;*

  

在构造函数中增加了对*listData1*进行内存分配，并生成数据最终绑定到*listBoxFrm1*，

  

*public Form1()*

  

*{*

  

*InitializeComponent();*

  

*this.listData1 = new ArrayList();*

  

*this.listData1.Add("DotNet");*

  

*this.listData1.Add("C#");*

  

*this.listData1.Add("Asp.net");*

  

*this.listData1.Add("WebService");*

  

*this.listData1.Add("XML");*

  

*this.listBoxFrm1.DataSource = this.listData1;*

  

*}*

  

另外，对修改按钮点击事件处理函数的修改如下：

  

*private void buttonEdit_Click(object sender, System.EventArgs e)*

  

*{*

  

*Form2 formChild = new Form2(this.listData1);*

  

*formChild.ShowDialog();*

  

*this.listBoxFrm1.DataSource = null;*

  

*this.listBoxFrm1.DataSource = this.listData1;*

  

*}*

  

相对与主窗体，对子窗体作相应修改，也在*Form2*中增加了类数据成员：

  

*private ArrayList listData2;*

  

用来保存对主窗体中*listData1*的引用。

  

修改构造函数：

  

*public Form2(ArrayList listData)*

  

*{*

  

*InitializeComponent();*

  

*this.listData2 = listData;*

  

*foreach(object o in this.listData2)*

  

*{*

  

*this.listBoxFrm2.Items.Add(o);*

  

*}*

  

*}*

  

这里让*listData2*同*listData1*指向同一个引用；另外没有对*listBoxFrm*进行绑定，采用了填充。

  

好了，下面是对数据操作的时候了。

  

添加处理函数代码如下：

  

*private void buttonAdd_Click(object sender, System.EventArgs e)*

  

*{*

  

*if(this.textBoxAdd.Text.Trim().Length>0)*

  

*{*

  

*this.listData2.Add(this.textBoxAdd.Text.Trim());*

  

*this.listBoxFrm2.Items.Add(this.textBoxAdd.Text.Trim());*

  

*}*

  

*else*

  

*MessageBox.Show("*请输入添加的内容*!");*

  

*}*

  

删除处理代码如下：

  

*private void buttonDel_Click(object sender, System.EventArgs e)*

  

*{*

  

*int index = this.listBoxFrm2.SelectedIndex;*

  

*if(index!=-1)*

  

*{*

  

*this.listData2.RemoveAt(index);*

  

*this.listBoxFrm2.Items.RemoveAt(index);*

  

*}*

  

*else*

  

*MessageBox.Show("*请选择删除项或者没有可删除的项*!");*

  

*}*

  

退出*Form2*子窗体：

  

*private void buttonOK_Click(object sender, System.EventArgs e)*

  

*{*

  

*this.Close();*

  

*}*

  

编译运行程序，在子窗体中对数据进行修改，关闭后，主窗体就会显示更新后的数据。

  

这里有一点要提醒一下，比较两个例子，我们都传的是引用类型，一个是*String*，另一个是*ArrayList*，为什么*string*类型不能修改主窗体的数据呢？其实在*.Net*中对*string*类型的修改并不是修改原来的值，原来的值没有变化，而是重新生成一个新的字符串，下面是一个很好的说明。

  

*public class ZZConsole*

  

*{*

  

*[STAThread]*

  

*static void Main(string[] args)*

  

*{*

  

*string str1 = "abc";*

  

*string str2 = str1;*

  

*str1 = "123";*

  

*Console.WriteLine(str1);*

  

*Console.WriteLine("--------------");*

  

*Console.WriteLine(str2);*

  

*Console.WriteLine("--------------");*

  

*ArrayList al1 = new ArrayList();*

  

*al1.Add("abc");*

  

*ArrayList al2 = al1;*

  

*al2.Add("123");*

  

*foreach(object o in al1)*

  

*Console.WriteLine((string)o);*

  

*Console.WriteLine("--------------");*

  

*foreach(object o in al2)*

  

*Console.WriteLine((string)o);*

  

*Console.ReadLine();*

  

*}*

  

*}*

  

运行一下看看输出结果就明白了，另外对值类型的数据操作要使用*ref*关键字。

  

总结，我们通过带参数的构造函数实现了窗体间的数据交互，代码看上去也比较清楚，在实际开发过程中，可以把*DataSet*，*DataTable*，或者是*DataView*当作参数，当然如果只是想修改一行，可以传个*DataRow*或者*DataRowView*。

---
本页由 梦飞idc云平台（https://www.mfisp.com）提供。站点导航见 https://www.mfisp.com/llms.txt
