當問題切割到最小求得這個小問題的解之後
再將這些小問題的解傳回來組合成最終解答
一般經典的例子就是求費氏數列
遞迴也像俄羅斯娃娃一樣
一個娃娃裡面有一個娃娃,這個娃娃裡面又有一個娃娃…
實務上遇到一個問題
如果一個畫面的控制項某些一開始載入的時候就要設為ReadOnly
那麼應該怎麼做?
最直接的方法當然就是Page_Load()的時候開始寫
TextBox1.ReadOnly=true; TextBox2.ReadOnly=true; TextBox3.ReadOnly=true; TextBox4.ReadOnly=true;
以上只有四個物件需要設定成ReadOnly
那如果有100個物件需要設定呢?
而且有不同的物件也要做不同處理呢?
當然不是真的去寫100行
身為程式設計師就要用程式設計師的方法去偷懶~
首先先聊聊WebForm的控制項特性
WebForm的控制項其實本身就是一種容器的概念
也就是一個控制項裡面可能還有其他控制像
其中的控制項裡面可能又有其他的控制項…
就像上面提到的俄羅斯娃娃一樣
所有控制項的父類別來自於Control
所以從多型(Polymorphism)的觀點來看
TextBox是Control
DropDownList也是Control
如果我們能夠取得控制項中的控制項
又能分辨出這個控制項是誰這問題就解決了
解法如下
private void SetDisable(ControlCollection Controls) { foreach (var obj in Controls) { if (obj is Control && (obj as Control).HasControls()) { SetDisable((obj as Control).Controls); } if (obj is TextBox && (obj as TextBox).ID != txtMemo.ID && (obj as TextBox).ID != txtDocWord.ID) { (obj as TextBox).ReadOnly = true; continue; } if (obj is DropDownList && (obj as DropDownList).ID != ddlModifyCategory.ID) { (obj as DropDownList).Enabled = false; continue; } } }
SetDisable這個方法有一個傳入的引數型態就是ControlCollection
在Control類別底下就有Controls這個屬性
他代表這個物件中包含的其他控制項物件
ControlCollection就是代表了一個控制項的集合
所以我們能用foreach (var obj in Controls)去取得其中的全部子控制項物件
並且用C#的隱含型別去接從Controls得到的物件
當然也可以用Object型別去接
接下來這段也就是多型跟遞迴應用的部份
if (obj is Control && (obj as Control).HasControls()) { SetReadOnly((obj as Control).Controls); }
obj is Control其中的is是C#用來檢查左邊的物件是否是右邊的型別
在此就是判斷說你取得的物件是否是Control類別的物件
如果他是Control類別的物件
那就代表他一定有Controls這個屬性
Controls本身也有提供HasControls()判斷裡面還有沒有控制項並回傳true或false
如果是Control類別的物件而且HasControls()為true就會進入該判斷式
並且再呼叫一次SetDisable傳入該物件的Controls集合
繼續檢查這個集合中的控制項是否還有子控制項
如果HasControls()為false表示沒有子控制項了
就繼續下面流程
下面流程主要也只是判斷這個物件是不是TextBox跟DropDownList
因為繼承Control的類別很多
但我們要設定的也只有TextBox跟DropDownList
因為在is的部份就已經確定是否為TextBox或DropDownList
所以後面使用as轉型一定不會失敗
之後依照型別做相對應的設定
沒有留言:
張貼留言