iT邦幫忙

DAY 2
16

ASP.NET 伺服器控制項開發系列 第 2

[ASP.NET 控制項實作 Day2] 建立第一個伺服器控制項

上一篇中已經建立「ASP.NET 伺服器控制項」專案,接下來我們將學習來撰寫第一個伺服器控制項。
撰寫伺服器控制項大致分為下列三種方式
1.由無到有建立全新的控制項,一般會繼承至 System.Web.UI.Control 或 System.Web.UI.WebControls.WebControl 類別。
2.繼承現有控制項,擴展原有控制項的功能,如繼承原有 TextBox 來擴展功能。
3.複合式控制項,將多個現有的控制項組合成為一個新的控制項,例如 TextBox 右邊加個 Button 整合成一個控制項,一般會繼承至 System.Web.UI.WebControls.CompositeControl 類別。

本文將先介紹第1種方式,由無到有來建立控制項,後面的文章中會陸續介紹第2、3種方式的控制項。要建立全新的控制項會繼承至 Control 或 WebControl,沒有 UI 的控制項可由 Control 繼承下來 (如 SqlDataSource),具 UI 的控制項會由 WebControl 繼承下來。接下來的範例中,我們將繼承 WebControl 來建立第一個 MyTextBox 控制項。

一、新增 MyTextBox 控制項
在 Bee.Web 專案按右鍵選單,執行「加入\新增項目」,選擇「ASP.NET 伺服器控制項」,在名稱文字框中輸入 MyTextbox,按下「確定」鈕,就會在專案中加入 MyTextbox 控制項類別。

新加入的控制項預設有一個 Text 屬性,以及覆寫 Render 方法。Render 方法是「將控制項呈現在指定的 HTML 寫入器中」,簡單的說就是在 Render 方法會將控制項對應的 HTML 碼輸出,用來呈現在用戶端的瀏覽器上。假設我們要撰寫一個網頁上的文字框,那就先去看一下文字框在網頁中對應的 HTML 碼,然後在 Render 方法中想辨法輸出這些 HTML 碼即可。

二、輸出控制項的 HTML 碼
你可以使用 FrontPage 之類的 HTML 編輯器,先編輯出控制項的呈現方式,進而去觀查它的 HTML 碼,再回頭去思考如何去撰寫這個伺服器控制項。假設 MyTextbox 控制項包含一個文字框及一個按鈕,那最終輸出的 HTML 碼應該如下。

<input id="Text1" type="text" />
<input id="Button1" type="button" value="button" />

我們在 MyTextbox 的 RenderContents 方法中輸出上述的 HTML 碼。

    Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
        Dim sHTML As String

        sHTML = "<input id=""Text1"" type=""text"" />" & _
                "<input id=""Button1"" type=""button"" value=""button"" />"
        writer.Write(sHTML)
    End Sub

建置控制項專案,然後拖曳 MyTextbox 在測試頁面上,設計階段就會呈現出我們期望的結果。

執行程式,在瀏覽器看一下 MyTextbox 控制項輸出的結果,是不是跟我們預期的一樣呢。

三、屬性套用到控制項 HTML 碼
控制項不可能單純這樣輸出 HTML 碼而已,控制項的相關屬性設定,一般都影響到輸出的 HTML 碼。假設 MyTextbox 有 Text 及 ButtonText 二個屬性,分別對應到 文字框的內容及按鈕的文字,MyTextbox 本來就有 Text 屬性,依像畫蘆葫新增 ButtonText 屬性。

    < _
    Bindable(True), _
    Category("Appearance"), _
    DefaultValue(""), _
    Localizable(True)> _
    Property ButtonText() As String
        Get
            Dim s As String = CStr(ViewState("ButtonText"))
            If s Is Nothing Then
                Return String.Empty
            Else
                Return s
            End If
        End Get

        Set(ByVal Value As String)
            ViewState("ButtonText") = Value
        End Set
    End Property

RenderContents 方法改寫如下。

    Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
        Dim sHTML As String

        sHTML = "<input id=""Text1"" type=""text"" value=""{0}""/>" & _
                "<input id=""Button1"" type=""button"" value=""{1}"" />"
        sHTML = String.Format(sHTML, Me.Text, Me.ButtonText)
        writer.Write(sHTML)
    End Sub

重新建置控制項專案,在頁面上測試 MyTextbox 的 Text 及 ButtonText 屬性。

四、使 ClientID (HTML 原始碼控制項的 ID) 是唯一值
在頁面上放置二個 MyTextbox 控制項,執行程式,在瀏覽器中檢查 MyTextbox 的 HTML 原始碼。你會發現 MyTextbox 會以一個 span 包住控制項的內容,而每個控制項的輸出的 ClientID 是唯一的。不過 MyTextbox 內含的文字框及按鈕卻會重覆,所以一般子控制項的 ClientID 會在前面包含父控制項的 ID。

<span id="MyTextbox1">
<input id="Text1" type="text" value="這是文字"/>
<input id="Button1" type="button" value="這是按鈕" />
</span>

<br />

<span id="MyTextbox2">
<input id="Text1" type="text" value="這是文字"/>
<input id="Button1" type="button" value="這是按鈕" />
</span>

所以我們再次修改 RenderContents 方法的程式碼

    Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
        Dim sHTML As String

        sHTML = "<input id=""{0}_Text"" type=""text"" value=""{1}""/>" & _
                "<input id=""{0}_Button"" type=""button"" value=""{2}"" />"
        sHTML = String.Format(sHTML, Me.ID, Me.Text, Me.ButtonText)
        writer.Write(sHTML)
    End Sub

執行程式,再次檢視 HTML 原始碼,所有的 ClinetID 都會是唯一的。

<span id="MyTextbox1">
<input id="MyTextbox1_Text" type="text" value="這是文字"/>
<input id="MyTextbox1_Button" type="button" value="這是按鈕" />
</span>

<br />

<span id="MyTextbox2">
<input id="MyTextbox2_Text" type="text" value="這是文字"/>
<input id="MyTextbox2_Button" type="button" value="這是按鈕" />
</span>

五、控制項前置詞
自訂控制項的預設前置詞是 cc1,不過這是可以修改的,在專案中的 AssemblyInfo.vb 檔案中,加入如下定義即可。詳細的作法請參考筆者部落格中的「自訂伺服器控制項前置詞」一本有詳細介紹,在此不再累述。

'設定控制項的標記前置詞
<Assembly: TagPrefix("Bee.Web.WebControls", "bee")>

六、結語
本文中是用土法鍊鋼的方法在撰寫伺服器控制項,一般在實作控制項時會有更好的方式、更易維護的寫法,後續的文章中會陸續介紹相關作法。

備註:本文同步發佈於筆者「ASP.NET 魔法學院」部落格
http://www.dotblogs.com.tw/jeff377/archive/2008/10/03/5573.aspx


上一篇
[ASP.NET 控制項實作 Day1] 建立 ASP.NET 伺服器控制項專案
下一篇
[ASP.NET 控制項實作 Day3] 擴展現有伺服器控制項功能
系列文
ASP.NET 伺服器控制項開發40

尚未有邦友留言

立即登入留言