2016年4月17日 星期日

[ASP.NET WebForm] 遞迴搭配多型實務應用

遞迴本身就是一種把問題切割成更小的問題求解

當問題切割到最小求得這個小問題的解之後

再將這些小問題的解傳回來組合成最終解答

一般經典的例子就是求費氏數列

遞迴也像俄羅斯娃娃一樣

一個娃娃裡面有一個娃娃,這個娃娃裡面又有一個娃娃…


實務上遇到一個問題

如果一個畫面的控制項某些一開始載入的時候就要設為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轉型一定不會失敗

之後依照型別做相對應的設定

沒有留言:

張貼留言