在.net中轻松掌握Windows窗体间的数据交互

** 在 .net ** ** 中轻松掌握 Windows ** ** 窗体间的数据交互 **

** ** zhzuo( 秋枫 )

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

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

** 一.使用带参数的构造函数
** 我们要做的准备工作就是新建两个窗体,下面是两个窗体的布局,很简单:
主窗体 子窗体

< 第一个例子 >

说明: 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 也是。

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

修改了两个窗体:
主窗体 子窗体

< 第二个例子 >

说明:在这个例子中我们的两个窗体都加了一个 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 。在下面的文章中我们来看看怎样使用另外两种方法来实现数据的交互。

** 二.给窗体添加属性或方法 ** ** **

** 1 ** ** .使用 ** ** Form ** ** 类的 ** ** Owner ** ** 属性 **

获取或设置拥有此窗体的窗体。若要使某窗体归另一个窗体所有,请为其 Owner <SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-hansi-font

Published At
Categories with Web编程
Tagged with
comments powered by Disqus