很多看似复杂、毫无头绪的属性或方法,其实只要追本溯源,一步一步向上找到它的父类以及实现的接口,常常问题会迎刃而解。
比如窗体中各种控件的属性方法,看似很复杂很抽象,其实找到他们的父类就会发现,无非是一些集合的子类。(如Form的control、listBox、combox等)因此在操作他们时大可按照平时操作单纯集合类的方法来进行。
实例:北大青鸟第6阶段上机作业
A、(拖界面角度上看)foreach (Control control in this.Controls)查找窗体中控件的顺序是:按控件拖进窗体的先后顺序,从后向前遍历。即后拖进窗体的控件先找到。
B、(代码角度上看)本质上就是按窗体中控件加载(this.Controls.Add方法)的顺序(先加载的先找到):
this.Controls.Add(this.label2);
this.Controls.Add(this.linkLabel1);
this.Controls.Add(this.button1);
如果窗体中的代码是上面这样的,那么找到的先后顺序就是label2、linkLabel1、button1。
C、以此类推,所有容器(如GroupBox、Panel等有add方法的容器)的遍历顺序也是一样的。
D、推理步骤:
第一步:找到Controls是ControlCollection类型的。
public class ControlCollection : ICollection, IEnumerable。
第二步:由于ControlCollection类实现了IEnumerable接口,所以它实现了GetEnumerator方法。GetEnumerator方法是支持foreach遍历的前提条件。
由于ControlCollection类实现了ICollection接口,说明它是一个集合类型。必然有与其他集合类型(List、ArrayList等)相似的方法。
第三步:List集合遍历的时候是按add添加的顺序向后遍历的。所以得出:只要是实现ICollection, IEnumerable接口的类,那么遍历的顺序和方法都是一样的!!!!
示例关键代码:
/// <summary>
/// 得到用户的答案
/// </summary>
/// <param name="form">题目所在的窗体</param>
/// <returns>返回用户选择的答案</returns>
public static List<string> GetUserAnswer(Form questionForm)
{
//定义一个集合接受用户的答案
List<string> userAnswer=new List<string>();
//遍历窗体中的控件
foreach (Control controlInForm in questionForm.Controls)
{
//得到窗体中的所有GroupBox类型控件(RadioButton在GroupBox中,遍历窗体Form无法得到RadioButton)
if (controlInForm is GroupBox)
{
//得到所有GroupBox类型控件中的所有选中的RadioButton控件
foreach (Control controlInGroupBox in controlInForm.Controls)
{
if (((RadioButton)controlInGroupBox).Checked == true)
{
//把选中的答案添加到用户答案表中
userAnswer.Add(((RadioButton)controlInGroupBox).Text);
}
}
}
}
//由于得到的用户答案顺序是倒的(后拖进窗体的控件先找到),因此必须倒转一次才是正确的顺序
userAnswer.Reverse();
return userAnswer;
}