上一篇中已经建立「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 属性,以及覆写 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 在测试页面上,设计阶段就会呈现出我们期望的结果。
执行程序,在浏览器看一下 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")>
六、结语
本文中是用土法炼钢的方法在撰写服务器控件,一般在实作控件时会有更好的方式、更易维护的写法,后续的文章中会陆续介绍相关作法。
备注:本文同步发布于「第一届iT邦帮忙铁人赛」,如果你觉得这篇文章对您有帮助,记得连上去推鉴此文增加人气 ^^
http://ithelp.ithome.com.tw/question/10011523