WinForm程序开发过程中,经常会遇到两个或多个窗体之间传递数据的情况,下面总结几种常用方法,以传递字符串为例。
方法一:使用属性传值(主窗体向子窗体传值)
1.新建一个Project,选择WindowsFormsApplication,命名为M1。主窗体界面如下:
2.在该项目上添加一个新的Windows 窗体,命名为Form2,界面如下:
3.修改Form2的构造函数,添加两个字符串变量,用来接受从Form1传递过来的数据,
public partial class Form2 : Form
{
private string str1, str2;
public Form2(string received1,string received2)
{
InitializeComponent();
str1 = received1;
str2 = received2;
}
}
4.双击Form2中的“接收”button,生成click事件,以便把从Form1接收到的数据在Form2界面上显示出来,
private void btnForm2_Click(object sender, EventArgs e)
{
this.textBox1.Text = str1;
this.textBox2.Text = str2;
}
5.双击Form1中的“生成Form2” button, 将Form2窗体实例化,并将Form1窗体中的两个textbox中的值传给Form2,
private void button1_Click(object sender, EventArgs e)
{
Form2 myForm2 = new Form2(textBox1.Text, textBox2.Text);
myForm2.Show();
}
总结:主窗体向子窗体传递的数据都是写在了构造函数的参数中,而在Form2的构造函数中已经确定了参数的类型和个数,所以此方法有一定的局限性,而且每一次传值都需要新构建一个子窗体,因此只能传递一次数据。
下面的方法介绍如何在两个窗体之间实时传递数据。
方法二:将主窗体直接传给子窗体。
重新定义子窗体的构造函数,参数类型为主窗体(即Form1)。主窗体在实例化子窗体时,就会把主窗体this指针传递进去。
1.主窗体添加一个textbox,一个trackBar,一个button,如下图:
2.子窗体设计如下:
3.Form1中代码如下:
public partial class Form1 : Form
{
//创建一个Form2的实例
private Form2 form2;
public Form1()
{
InitializeComponent();
}
private void btnForm1_Click(object sender, EventArgs e)
{
//将Form2实例化,并将主窗体this指针传给Form2
form2 = new Form2(this);
form2.Show();
}
private void trackBar1_ValueChanged(object sender, EventArgs e)
{
//当主窗体滑动条数值改变时,在Form2窗体中显示对应的值
form2.label2.Text = this.trackBar1.Value.ToString();
}
}
注意:form2.label2.Text = this.trackBar1.Value.ToString();
由于主窗体要将滑动条的value赋给Form2中的lable2,所以要在Form2的Form2.Designer.cs中将lable2的定义类型从private修改为public.
private System.Windows.Forms.Label label1;
public System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button btnForm2;
4.Form2中的代码如下:
public partial class Form2 : Form
{
private Form1 my_Form1;
public Form2(Form1 myForm1)
{
InitializeComponent();
this.my_Form1 = myForm1;
}
private void btnForm2_Click(object sender, EventArgs e)
{
this.textBox1.Text = my_Form1.textBox1.Text;
}
}
注意:同样,在Form2中,由于button的作用为将Form1中textbox中的数值显示在自己的窗体(即Form2的textbox)中,所以在Form1的Form1.Designer.cs中将textbox1的定义类型从private修改为public.
private System.Windows.Forms.Label label1;
public System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button btnForm1;
private System.Windows.Forms.TrackBar trackBar1;
总结:本例中通过修改Form2的构造函数,来接收Form1传递的数据。在Form2中定义了一个Form1类型的变量my_Form1,将Form2接收的主窗体指针赋给my_Form1,以此来达到传递数据的作用。在本例中也可以对btnForm2_Click(object sender, EventArts e)稍做修改,变成子窗体向主窗体发送数据,即实现了两个窗体之间数据的相互传递。在上面的方法二中要特别注意的是,如果要从自己的窗体直接访问别的窗体的数据时,一定要在对方窗体中将被访问的内容设为public,否则无法实现数据的传递。
方法三:使用委托(Delegate)和事件(Event)
1.主窗体设计如下:
2.子窗体设计如下:
3.在Form2中定义一个委托类型SendMesg
public delegate void SendMesg(string str);
定义一个事件Send
public event SendMesg Send;
4.双击Form2中的"传递" button,在它的click事件对应的代码中,修改如下。当点击"传递"button时,触发SendMsg事件,传递字符串,
private void button1_Click(object sender, EventArgs e)
{
SendMsg(this.textBox1.Text);
}
5.在Form1中代码如下,
public partial class Form1 : Form
{
private Form2 myForm = new Form2();
public Form1()
{
InitializeComponent();
myForm.SendMsg += new Form2.SendMesg(Receive);
}
private void button1_Click(object sender, EventArgs e)
{
myForm.Show();
}
private void Receive(string str)
{
this.textBox1.Text += str;
}
}
首先创建一个Form2的实例,然后订阅Form2中注册的事件,即myForm.SendMsg += new Form2.SendMesg(Receive);
最后通过Receive(string str)处理接收到的数据。
总结:在方法二中,如果要传递一个数值,需要把整个主窗体的引用都传递给子窗体,这种方法耦合度太高,使用委托可以很好的避免这个问题。