1、我定义了第一个窗口(winform1),在该窗口中放入三个文本框,分别是输入:数据库实例名(tb1)、用户名(tb2)和密码(tb3),然后有一个按钮(bt1),点击该钮后开始验证能否连接到数据库,如果连接成功,就打开第二个窗口(winform2);
2、winform2中定义了几个按钮,分别是针对数据库的一些操作,例如查找记录,修改记录等,点击相应功能按钮后就实现对应的功能,并且将数据显示到第三个窗口中(winform3);
3、winform3主要是负责显示数据;
现在的问题是,数据库连接信息主要是在winform1中的tb1、tb2、tb3中输入,第一个窗口只是测试连接的,但是调用winform2点击功能后,需要重新连接数据库,但是这个连接字符串如何获取winform1种用户输入的信息呢?
希望大家能够指点!!!
2、winform2中定义了几个按钮,分别是针对数据库的一些操作,例如查找记录,修改记录等,点击相应功能按钮后就实现对应的功能,并且将数据显示到第三个窗口中(winform3);
3、winform3主要是负责显示数据;
现在的问题是,数据库连接信息主要是在winform1中的tb1、tb2、tb3中输入,第一个窗口只是测试连接的,但是调用winform2点击功能后,需要重新连接数据库,但是这个连接字符串如何获取winform1种用户输入的信息呢?
希望大家能够指点!!!
http://blog.csdn.net/yumanqing/archive/2006/10/23/1346272.aspx
http://blog.csdn.net/yumanqing/archive/2006/10/23/1346272.aspx
方法2:从form1激活form2,同时传递连接数据,form2再激活form3,同时传递连接数据。
一.使用带参数的构造函数
我们要做的准备工作就是新建两个窗体,下面是两个窗体的布局,很简单:
<第一个例子>
说明: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也是。 到这里为止功能是实现了,但是总觉得不是很合理,让两个窗体控件传来传去
主窗体中控件: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();
}
编译运行程序,在子窗体中对数据进行修改,关闭后,主窗体就会显示更新后的数据。
二.给窗体添加属性或方法
1.使用Form类的Owner属性
获取或设置拥有此窗体的窗体。若要使某窗体归另一个窗体所有,请为其 Owner 属性分配一个对将成为所有者的窗体的引用。当一个窗体归另一窗体所有时,它便随着所有者窗体最小化和关闭。例如,如果 Form2 归窗体 Form1 所有,则关闭或最小化 Form1 时,也会关闭或最小化 Form2。并且附属窗体从不显示在其所有者窗体后面。可以将附属窗体用于查找和替换窗口之类的窗口,当选定所有者窗体时,这些窗口不应消失。若要确定某父窗体拥有的窗体,请使用OwnedForms属性。
上面是SDK帮助文档上讲的,下面我们就来使用它。
首先还是使用第一篇文章中的第二个例子,窗体如下:
说明:在这个例子中我们的两个窗体都加了一个ListBox用来显示ArrayList中的内容。主窗体中控件:listBoxFrm1,buttonEdit;子窗体中控件:listBoxFrm2,textBoxAdd,buttonAdd,buttonEdit,buttonOK。主窗体中还是定义类数据成员,private ArrayList 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(); formChild.Owner = this; formChild.ShowDialog(); this.listBoxFrm1.DataSource = null; this.listBoxFrm1.DataSource = this.listData1;}我们设置了formChild.Owner为this,这样,子窗体和主窗体就有联系了,当然我们也可以改成如下:private void buttonEdit_Click(object sender, System.EventArgs e){ Form2 formChild = new Form2(); formChild.ShowDialog(this); this.listBoxFrm1.DataSource = null; this.listBoxFrm1.DataSource = this.listData1;}不过这样还不行,目前主窗体的listData1变量外部访问不到,private ArrayList listData1;必须修改为public访问修饰符,public ArrayList listData1;也可以通过属性(property)来实现,public ArrayList ListData1{ get{return this.listData1;}}这里我采用属性,感觉语法更灵活,清楚。下面是对Form2的修改,构造函数又恢复原貌了。public Form2(){ InitializeComponent();}另外又新增了一个窗体的Load事件,在它的事件处理函数中来获取主窗体中的数据,private void Form2_Load(object sender, System.EventArgs e){ Form1 pareForm = (Form1)this.Owner; this.listData2 = pareForm.ListData1; foreach(object o in this.listData2) this.listBoxFrm2.Items.Add(o);}有人会问,为什么不把上面的代码放到构造函数里面去呢?如下不是更好,public Form2(){ InitializeComponent(); Form1 pareForm = (Form1)this.Owner; this.listData2 = pareForm.ListData1; foreach(object o in this.listData2) this.listBoxFrm2.Items.Add(o);}那我会对你说错了,因为在主窗体修改按钮被点击后,开始执行Form2 formChild = new Form2();而在Form2的实例化过程中会在构造函数中执行Form1 pareForm = (Form1)this.Owner;而这时的this.Owner是没有值的,为空引用,那么下面的代码肯定也出问题,this.listData2 = pareForm.ListData1;foreach(object o in this.listData2) this.listBoxFrm2.Items.Add(o);当整个Form2实例化完成后,才会执行formChild.Owner = this;这条代码,所以使用了Form2_Load事件。那怎样可以不使用Form2_Load事件呢?等下面我们来修改代码实现它。下面的子窗体代码没有变化,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("请选择删除项!");}private void buttonOK_Click(object sender, System.EventArgs e){ this.Close();}好了,结果同第一篇中的一样,子窗体能修改主窗体的值。2.使用自定义属性或方法下面我们来讲讲怎样使用自定义属性或方法来完成数据修改功能而不使用Form2_Load事件。主窗体的修改按钮点击处理函数如下: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属性,//public ArrayList ListData1//{// get{return this.listData1;}//}而在子窗体中加上ListData2属性,public ArrayList ListData2{ set { this.listData2 = value;
foreach(object o in this.listData2)
this.listBoxFrm2.Items.Add(o);
}
}
也可以把属性改成方法,
public void SetListData(ArrayList listData)
{
this.listData2 = listData;
foreach(object o in this.listData2)
this.listBoxFrm2.Items.Add(o);
}
而在主窗体的修改按钮处理函数中也要相应改动:
formChild.ListData2 = this.listData1;改为
formChild.SetListData(this.listData1);
使用静态类 这个也是我们经常要用到的一种数据交互方法。
下面是定义的一个类:
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。
http://blog.csdn.net/zhzuo/archive/2004/04/05/22027.aspx
窗体的参数传递
http://blog.csdn.net/zhzuo/archive/2006/05/05/708941.aspx#sec5