上一篇中已经建立「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 控件类别。

image

新加入的控件预设有一个 Text 属性,以及覆写 RenderContents 方法。RenderContents 方法是「将控件的内容呈现在指定的写入器」,简单的说就是输出控件对应的 HTML 码,用来呈现在客户端的浏览器上。假设我们要撰写一个网页上的文字框,那就先去看一下文字框在网页中对应的 HTML 码,然后在 RenderContents 方法中想辨法输出这些 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 在测试页面上,设计阶段就会呈现出我们期望的结果。

image

 

执行程序,在浏览器看一下 MyTextbox 控件输出的结果,是不是跟我们预期的一样呢。

image

 

三、属性套用到控件 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 属性。

image

 

四、使 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")>

 

六、结语

本文中是用土法炼钢的方法在撰写服务器控件,一般在实作控件时会有更好的方式、更易维护的写法,后续的文章中会陆续介绍相关作法。

 

备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10011523

posted on 2008-10-14 00:52  jeff377  阅读(480)  评论(0编辑  收藏  举报