1:经常使用control.Parent(或者mdiParent)或者control.Child(或mdiChild)这一属性,由它可以得到我们想要获得的任何控件实例引用,并对这些控件进行操作
例如一个窗体form1中有一个groupbox1,groupbox1中有一个richtextbox1,后者又包含一个linkbuttonClose1按钮,如果要通过单击该按钮来关闭groupbox1,则在该按钮的单击事件中可以这样写:
private void linkbuttonClose1_Click(Object sender,EventArgs e)
{
GroupBox gb=((sender).Parent).Parent as GroupBox;
gb.Hide();
gb.Dispose();
}
2:使用委托给事件赋值,而非直接写事件函数
如上例中的linkbuttonClose1_Click事件,我们可以将该事件名称随便改掉,例如改成
LinkButtonClick(Object sender,EventArgs e),然后将该方法(已不是事件)赋值给linkbuttonClose1按钮的单击事件:
linkbuttonClose1.Click+=new EventHanler(LinkButtonClick),这样会让程序更加灵活
3:遍历子控件
在上面提到要经常使用control.Parent属性,如果要查询一个控件中的所有子控件,则可以遍历其所有子控件,并可以通过子控件的名称、文本或类型名来获取相应的子控件,例如:
private Control GetChild(Control control)
{
foreach(Control child in control.Controls)
{
if(child.Gettype().Name.Equals("GroupBox"))
{
GroupBox g=child as GroupBox;
return g;
}
else if(child.Child.Count>0)
{
GetAllChildren(child); //如果没有找到则继续遍历
}
}
return null;
}
上面的遍历方法会返回某个控件中的第一个类型为GroupBox的控件。
现在以上面列举的窗体、分组框、文本框和按钮这四个依次被包容的控件为例,如果现在要通过窗体找到按钮(如果事先知道这些控件的包容关系),则可以这样:
foreach(Control child in form1.Controls)
{
if(child.Name.Equals("groupbox1"))
{
foreach(Control child2 in child.Controls)
{
if(child2.Name.Equals("richtextbox1"))
{
foreach(Control child3 in child2.Controls)
{
if(child3.Name.Equals("linkbuttonClick1"))
{
linkbuttonClick1.Click+=new EventHandler(LinkButtonClick);
}
}
}
}
}
}
上面的循环中都是通过控件的Name属性来获取相应的控件,如果控件有Text属性,则也可以通过该属性来得到该控件,例如gourpbox就有text属性。
4:必须理解一点:控件都是引用类型,而非值类型,因此当把控件作为参数传递进一个方法中,并且在该方法中对该控件参数进行了操作,则方法体外的真实控件
将被进行同样的操作,因为方法体内和方法体外的两个控件指向同一个引用。这样便可以大大提高程序的灵活性,最典型的应用便是将窗体做为参数进行传递,
这样便可以实现一个窗体对另一个窗体的操作,或者是实现窗体之间的通信。窗体之间的通信一般是通过修改窗体的构造函数类实现,还是以上面列举的几个控件为例:
点击form1窗体中的linkbuttonClose按钮,则form1被关闭或被隐藏,而show出一个form2,并且要让form2来获取form1中的richtextbox中的文本信息,
可以如下操作:
在form1窗体类中的linkbuttonClose单击事件中写入:
private void linkbuttonClose1_Click(Object sender,EventArgs e)
{
Form2 form2=new Form2(this);
this.Hide();
form2.Show();
}
在form2的窗体类中声明一个Form1的实例:private Form1 form1;
将form2默认的构造函数public Form2(){InitialComponent();}改成:
public Form2(Form1 form1)
{
this.form1=form1;
}
然后就可以在form2中对form1进行操作了,包括获取其中的文本框文本信息,例如可以通过遍历form1来获得其中的文本框:
string str;
foreach(Control child in form1.Controls)
{
if(child.Name.Equals("groupbox1"))
{
foreach(Control child2 in child.Controls)
{
if(child2.Name.Equals("richtextbox1"))
{
str=child.Text;
}
}
}
}
为了要让form2获取form1的引用,并不只是通过传递form1可以做到,也可以通过传递form1中的任何一个子控件都可以做到,例如传递form1
中的linkbuttonClose1,首先在form2中声明一个LinkButton实例,然后在form2的构造函数中给其赋值:
Class Form2:Form
{
private LinkButton lb=null;
pulib Form2(LinkButton lb)
{
this.lb=lb;
}
string str="";
private void GetRichTextBox()
{
RichTextBox rtb=lb.Parent as RichTextBox; /*此时rtb实例指向lb的父容器即form1中的richtextbox1,
*对rtb的任何操作都相当于在操作form1中的richtextbox1*/
str=rtb.Text;
}
}
5:反射技术在窗体程序中的重要应用
由于不同窗体之间传递数据比较麻烦,因此反射技术得到了广泛的应用,还和上面的例子相同,要form2获取form1中的richtextbox1中的文本信息,
首先在form1中的linkbuttonClose单击事件中写入:
private void linkbuttonClose1_Click(Object sender,EventArgs e)
{
string assemblyName="......"; //该字符串指向form2窗体类的namespace即命名空间的名称
string className="Form2"; //窗体form2的类名
Type type=Type.Gettype(assemblyName+"."+className); //获取form2的类型
Form2 form2=System.Activator.CreateInstance(type); //创建form2实例
//调用form2中的GetRichTextBox(Form param)方法
MethodInfo mi = form2.GetType().GetMethod(GetRichTextBox);
mi.Invoke(form2,new Object[]{this});
}
这样,form2中的GetRichTextBox(Form param)中的参数param便是form1的实例了,然后我们可以通过遍历的方法来找到form1中的richtextbox1并
获取其文本值。
在上面通过反射方法调用时,可以传入多个参数,例如可以将form1连同其richtextbox1一起传递:
mi.Invoke(form2,new Object[]{this,this.richtextbox1});
然后form2中的GetRichTextBox方法的参数列表也要改变为两个参数:
GetRichTextBox(Form param , RichTextBox rtb){}
现在,该参数列表中的rtb便是form1中的richtextbox1了,对rtb的任何操作都会同时影响form1中的richtextbox1,当然也就包括取值,此时
我们便可以直接获取rtb.Text。