我們先看幾個類圖,深入認識一下我們常用的WinForm控件:
圖1 ScrollableControl類圖
圖2 ButtonBase類圖
圖3 TextBoxBase類圖
圖4 ListControl類圖
圖5 Label類圖
圖6 其它常用
從圖1中可以看出,Form與Button、Label一樣,也是一個Control。
WinForm中的一些控件(如Form、GroupBox、Panel)可以包含其它控件,我們可以通過Control類的Controls屬性進行遍歷。控件是可以層層包含的,如下圖:
圖7 示例窗體
Form1是頂級控件,它包含了四個子控件:groupBox1、groupBox2、button1、button2。groupBox1和groupBox2中也包含了多個控件。層層包含最終形成了一個樹型結構。
我們打造的WinForm的控件選擇器,實質上就是一個樹的遍歷器。下是就是該選擇器的參考實現代碼:
1 public static IEnumerable<T> GetControls<T>(this Control control, Func<T, bool> filter) where T : Control
2 {
3 foreach (Control c in control.Controls)
4 {
5 if (c is T)
6 {
7 T t = c as T;
8 if (filter != null)
9 {
10 if (filter(t))
11 {
12 yield return t;
13 }
14 else
15 {
16 foreach (T _t in GetControls<T>(c, filter))
17 yield return _t;
18 }
19 }
20 else
21 yield return t;
22 }
23 else
24 {
25 foreach (T _t in GetControls<T>(c, filter))
26 yield return _t;
27 }
28 }
29 }
(代碼中存在一處bug,請參見斯克迪亞的回復#4樓)
有了GetControls選擇器,我們就可以在WinForm中進行一些“復雜”應用,示例如下(以圖7為例):
1 // 構造函數
2 public Form1()
3 {
4 InitializeComponent();
5 //禁用所有Button
6 this.GetControls<Button>(null).ForEach(b => b.Enabled = false);
7 //反選groupBox1中CheckBox
8 this.GetControls<CheckBox>(c => c.Parent == groupBox1)
9 .ForEach(c => c.Checked = !c.Checked);
10 //將label1的前景色設為紅色
11 this.GetControls<Label>(l => l.Name == "label1").FirstOrDefault().ForeColor
12 = Color.Red;
13 }
附上常用的ForEach擴展:
1 public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
2 {
3 foreach (var item in source)
4 action(item);
5 }
感覺如何?歡迎批評指正!