关于C#窗体间的数据传值的方法好几种,在项目中都各有应用,虽然简单,这里记录下来,分享给大家!
一、使用带参数的构造函数
主窗体
1 2 3 4 5 6
| private void button_Click(object sender, System.EventArgs e) { Form2 formChild = new Form2(this.textBoxFrm1.Text, this.checkBoxFrm1.Checked); formChild.ShowDialog(); }
|
子窗体(Form2)
1 2 3 4 5 6 7
| Public Form2(string text, bool checkedValue) { InitializeComponent(); this.textBoxFrm2.Text = text; this.checkBoxFrm2.Checked = checkedValue; }
|
但是这种传值存在不足,在子窗体里的数据修改后不能传给主窗体,也就是说主窗体不受子窗体的影响。而在实际的开发过程中我们经常使用子窗体来修改主窗体里面的数据。
二、 在.NET中有两种类型,值类型和引用类型。
值类型是从ValueType继承而来,而ValueType又是从Object继承;对于引用类型它直接继承Object类型。这下让我们看看怎样利用引用类型来通过Form2来修改Form1里的数据。
子窗体代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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; }
private void buttonOK_Click(object sender, System.EventArgs e) { this.textBoxFrm12.Text = this.textBoxFrm2.Text; this.checkBoxFrm12.Checked = this.checkBoxFrm2.Checked; this.Close(); }
|
这里也实现了传值的功能,但是总觉得不是很合理,总是让两个窗体控件传来传去,很烦,如果控件多了呢。当然我们可以将需要修改值的控件封装到自定义的结构体中,但是….我们再来看看下面一种传值方式吧。
三、C#窗体间通过ArrayList传值
主窗体代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
private ArrayList listData; public Form1() {
InitializeComponent();
listData = new ArrayList();
listData.Add(".Net");
listData.Add("Java");
listData.Add("XML");
listData.Add("WebService");
listBox1.DataSource = listData;
}
private void buttonOpen_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2(listData);
frm2.ShowDialog();
listBox1.DataSource = null;
listBox1.DataSource = listData;
}
|
关于”设置DataSource属性后无法修改项集合”错误,参考http://www.ideaext.com/read.php/312.htm
子窗口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| ArrayList listData;
public Form2(ArrayList listData) {
InitializeComponent();
this.listData = listData;
foreach (object da in listData) {
listBox1.Items.Add(da);
}
}
private void buttonAdd_Click(object sender, EventArgs e) {
if (this.textBox1.Text.Trim().Length > 0) {
this.listData.Add(this.textBox1.Text.Trim());
this.listBox1.Items.Add(this.textBox1.Text.Trim());
}
else
MessageBox.Show("请输入添加的内容!");
}
private void buttonDel_Click(object sender, EventArgs e) {
int index = this.listBox1.SelectedIndex;
if (index != -1) {
this.listData.RemoveAt(index);
this.listBox1.Items.RemoveAt(index);
}
else
MessageBox.Show("请选择删除项或者没有可删除的项!");
}
private void buttonExit_Click(object sender, EventArgs e) {
this.Close();
}
|
这里有一点要提醒一下,比较两个例子,我们都传的是引用类型,一个是String,另一个是ArrayList,为什么string类型不能修改主窗体的数据呢?其实在.Net中对string类型的修改并不是修改原来的值,原来的值没有变化,而是重新生成一个新的字符串,下面是一个很好的说明。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| public class PdtGrp {
[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。
四、使用自定义属性或方法
下面我们来讲讲怎样使用自定义属性或方法来完成数据修改功能而不使用Form2_Load事件。
主窗体的修改按钮点击处理函数如下:
1 2 3 4 5 6 7 8
| private void buttonEdit_Click(object sender, System.EventArgs e) { Form2 formChild = new Form2(); formChild.ListData2 = this.listData1; formChild.ShowDialog(); this.listBoxFrm1.DataSource = null; this.listBoxFrm1.DataSource = this.listData1; }
|
并且我们去掉了主窗体的ListData1属性,
而在子窗体中加上ListData2属性,
1 2 3 4 5 6 7 8 9
| public ArrayList ListData2 { set { this.listData2 = value; foreach (object o in this.listData2) this.listBoxFrm2.Items.Add(o); } }
|
也可以把属性改成方法,
1 2 3 4 5 6
| public void SetListData(ArrayList listData) { this.listData2 = listData; foreach (object o in this.listData2) this.listBoxFrm2.Items.Add(o); }
|
而在主窗体的修改按钮处理函数中也要相应改动:
1
| formChild.ListData2 = this.listData1;
|
改为
1
| formChild.SetListData(this.listData1);
|
总结,我们通过Form类的Owner属性来建立主从窗体间的桥梁,这个是不是类似于把主窗体作为子窗体的构造函数参数传入实现的功能差不多;另外又采用了属性和方法来完成数据的交互,我觉得这种实现方法很实用,特别是用在不需要实例化类或着已经有了实例的情况下传递数据。下一节我们来讲如何使用静态类来完成数据的交互。
五、使用静态类
之前使用带参数的构造函数、属性以及方法实现了数据的交互,接下来的是使用静态类来完成窗体间的数据交互。这也是经常要用到的一种数据交互方法。
下面是定义的一个类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| using System; using System.Collections; namespace ZZ { public class AppDatas { private static ArrayList listData; static AppDatas() { listData = new ArrayList(); listData.Add("DotNet"); listData.Add("C#"); listData.Add("Asp.net"); listData.Add("WebService"); listData.Add("XML"); }
public static ArrayList ListData { get { return listData; } }
public static ArrayList GetListData() { return listData; } } }
|
上面包含了一个静态类成员,listData,一个静态构造函数static AppDatas(),用来初始化listData的数据。还有一个静态属性ListData和一个静态GetListData()方法,他们实现了同样的功能就是返回listData