ASP.NET控件開(kāi)發(fā)之RenderContents使用淺析
ASP.NET控件開(kāi)發(fā)基礎(chǔ)之RenderContents使用呈現(xiàn)自定義控件的步驟:
ASP.NET控件開(kāi)發(fā)之RenderContents使用一.從繼承WebControl開(kāi)始
在第二篇教程中,重點(diǎn)介紹了Render()方法的使用,用來(lái)呈現(xiàn)控件,但從Control類(lèi)繼承的控件尚未發(fā)揮asp.net控件的作用.大家知道web服務(wù)器控件分為HTML服務(wù)器控件(如﹤input id="Button2" runat="server" type="button" value="button" /﹥這樣的形式)和標(biāo)準(zhǔn)服務(wù)器控件(就是﹤asp:.. id="" runat="server" /﹥這樣的形式的控件)
HTML服務(wù)器控件的控件從System.Web.UI.HtmlControls.HtmlControl 類(lèi)派生
標(biāo)準(zhǔn)服務(wù)器控件的控件從System.Web.UI.WebControls.WebControl 類(lèi)派生
HtmlControl 類(lèi)和WebControl 類(lèi)則從System.Web.UI.Control 類(lèi)派生,并擴(kuò)展.
所以我們說(shuō),所有的服務(wù)器控件都繼承自System.Web.UI.Control 類(lèi),即所有的服務(wù)器控件都具有Control 類(lèi)的共同屬性,如Visible,EnableViewState屬性,HtmlControl 類(lèi)和WebControl 類(lèi)則擴(kuò)充了System.Web.UI.Control 類(lèi)的功能,如
HtmlControl 類(lèi)定義了所有 HTML 服務(wù)器控件所通用的方法、屬性 (Property) 和事件(具體參數(shù)參照MSDN)
WebControl 類(lèi)定義了所有 標(biāo)準(zhǔn)服務(wù)器控件所通用的方法、屬性 (Property) 和事件(具體參數(shù)參照MSDN)
如每個(gè)繼承了WebControl 類(lèi)的標(biāo)準(zhǔn)控件都有定義外觀和行為的屬性,然后不同控件再根據(jù)需要擴(kuò)展功能.
所以我們推薦的做法是直接從WebControl 類(lèi)派生,而非Control類(lèi).我們所做的非并從頭開(kāi)始.從WebControl 類(lèi)繼承可以幫我們省很多工作.
ASP.NET控件開(kāi)發(fā)之RenderContents使用二.重寫(xiě)WebControl類(lèi)方法,不再是Render()
WebControl類(lèi)繼承了Control類(lèi),當(dāng)然有Render方法,在WebControl類(lèi)中重寫(xiě)了Render方法,如下代碼
示例一
- protected override void Render(HtmlTextWriter output)
- {
- RenderBeginTag(output);
- RenderContents(output);
- RenderEndTag(output);
- }
注意 RebderBeginTag方法并非是HtmlTextWriter類(lèi)中的方法,而是WebControl類(lèi)中的方法,表示輸出HTML標(biāo)簽頭標(biāo)記,如﹤table .....﹥,RenderEndTag方法則輸出HTML標(biāo)簽尾標(biāo)記,如﹤/table﹥.中間的RenderContents方法則就是Control類(lèi)的Render方法. 看下面RenderContents方法的定義.
示例二
- protected override void RenderContents(HtmlTextWriter output){
- //使用默認(rèn)邏輯來(lái)呈現(xiàn)子控件,那么一定要調(diào)用基類(lèi)中的方法。
- base.Render(output);
- }
接著再看RenderBeginTag方法的定義
示例三
- public virtual void RenderBeginTag(HtmlTextWriter output)
- {
- //添加呈現(xiàn)控件的屬性和樣式
- //AddAttributesToRender為WebControl類(lèi)中的方法
- AddAttributesToRender(output);
- //呈現(xiàn)控件標(biāo)簽
- //如label控件呈現(xiàn)﹤span ﹥
- //textbox控件呈現(xiàn)﹤input ﹥
- HtmlTextWriterTag tagKey = TagKey;
- if (tagKey != HtmlTextWriterTag.Unknown)
- {
- output.RenderBeginTag(tagKey);
- }
- else
- {
- output.RenderBeginTag(this.TagName);
- }
- }
這里打個(gè)比方,假設(shè)你要輸出一個(gè)表格,你就必須定義﹤table﹥標(biāo)簽頭,然后在其內(nèi)部定義﹤tr﹥,﹤td﹥,下面看Control類(lèi)中Render方法的實(shí)現(xiàn),表明Render方法必須完成所有的任務(wù),包括標(biāo)簽頭標(biāo)記﹤table﹥和﹤table﹥標(biāo)簽的屬性和樣式的輸出.
示例四
- protected override void Render(HtmlTextWriter writer)
- {
- //為table標(biāo)簽定義屬性和樣式
- writer.AddAttribute(HtmlTextWriterAttribute.Width, "287px");
- writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "0");
- writer.RenderBeginTag(HtmlTextWriterTag.Table);
- writer.RenderBeginTag(HtmlTextWriterTag.Tr);
- writer.RenderBeginTag(HtmlTextWriterTag.Td);
- writer.Write("﹤strong﹥" + PaymentMethodText + "﹤/strong﹥");
- writer.RenderEndTag();
- writer.RenderBeginTag(HtmlTextWriterTag.Td);
- writer.AddAttribute(HtmlTextWriterAttribute.Name, "PaymentMethod");
- writer.AddAttribute(HtmlTextWriterAttribute.Id, "PaymentMethod");
- writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "100%");
- writer.RenderBeginTag(HtmlTextWriterTag.Select);
- //以下代碼省略
- }
在WebControl類(lèi)中重寫(xiě)了Render方法后,直接幫你定義好了標(biāo)簽,默認(rèn)情況下為﹤span﹥,可通過(guò)重寫(xiě)TagKey屬性來(lái)修改標(biāo)簽,然后AddAttributesToRender方法為標(biāo)簽定義樣式和屬性
示例五
- protected override HtmlTextWriterTag TagKey
- {
- get { return HtmlTextWriterTag.Table; }
- }
示例六
- protected override void AddAttributesToRender(HtmlTextWriter writer)
- {
- //為table標(biāo)簽定義屬性和樣式
- writer.AddAttribute(HtmlTextWriterAttribute.Width, "287px");
- writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "0");
- base.AddAttributesToRender(writer);
- }
接著重寫(xiě)RenderContents方法,對(duì)比上面的Render方法,實(shí)現(xiàn)效果是一樣的
示例七
- protected override void RenderContents(HtmlTextWriter writer)
- {
- //注意,此處無(wú)沒(méi)有table標(biāo)簽,只定義其內(nèi)部標(biāo)簽
- writer.RenderBeginTag(HtmlTextWriterTag.Tr);
- writer.RenderBeginTag(HtmlTextWriterTag.Td);
- writer.Write(PaymentMethodText);
- writer.RenderEndTag();
- writer.RenderBeginTag(HtmlTextWriterTag.Td);
- writer.AddAttribute(HtmlTextWriterAttribute.Name, PaymentMethodSelectName);
- writer.AddAttribute(HtmlTextWriterAttribute.Id, PaymentMethodSelectId);
- writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "100%");
- writer.RenderBeginTag(HtmlTextWriterTag.Select);
- //以下省略
- }
所以說(shuō)重寫(xiě)后的Render方法在默認(rèn)情況下加了一個(gè)標(biāo)簽,而你可以重寫(xiě)這個(gè)標(biāo)簽(默認(rèn)情況下為﹤span﹥).可能大家對(duì)其感到奇怪,即然可以實(shí)現(xiàn)同樣效果,有必要重寫(xiě)Render方法,再加一個(gè)RenderContents方法嗎?
ASP.NET控件開(kāi)發(fā)之RenderContents使用三.Render方法和RenderContents方法的區(qū)別
當(dāng)你繼承WebControl類(lèi),在RenderContents方法中實(shí)現(xiàn)示例四代碼時(shí),(我們?cè)僖砸郧暗睦诱故?呈現(xiàn)后的代碼如下,看到?jīng)]有,控件ID為﹤span﹥
在RenderContents方法輸入的標(biāo)簽將成為其內(nèi)部標(biāo)簽.再看看這個(gè)控件的屬性面板,你會(huì)看到很多的繼承自WebControl類(lèi)的屬性,設(shè)置其屬性,即是設(shè)置﹤span﹥標(biāo)簽的屬性.TagKey的作用大概就在于此吧,為了使用WebControl類(lèi)的公共屬性.(我是這么認(rèn)為的)而非定義在﹤table﹥標(biāo)簽上
示例八
- ﹤span id="CreditCardForm5_1"﹥﹤table style="border-width:0;"﹥
- ﹤tr﹥
- ﹤td﹥﹤strong﹥信用卡類(lèi)型﹤/strong﹥﹤/td﹥﹤td﹥﹤select name="PaymentMethod" id="PaymentMethod" style="width:100%;"﹥
- ......
假設(shè)我們稱(chēng)﹤span﹥里面的﹤table﹥等標(biāo)簽為子標(biāo)簽,在RenderContents方法應(yīng)該定義控件的子標(biāo)簽,如果你只定義標(biāo)簽屬性的話,只需重寫(xiě)AddAttributesToRender方法即可,可不須重寫(xiě)RenderContents方法.
下面再講下重寫(xiě)標(biāo)簽的方法
(1) 重寫(xiě)TagKey屬性,下面重寫(xiě)label控件的標(biāo)簽
- public class Ch4Label: Label
- {
- protected override HtmlTextWriterTag TagKey
- {
- get { return HtmlTextWriterTag.Div; }
- }
- }
(2)重寫(xiě)基類(lèi)構(gòu)造函數(shù),此方法只有在繼承Control類(lèi)后適用
- public CreditCardForm5() : base(HtmlTextWriterTag.Table) { }
最后總結(jié)下:
1.控件繼承自WebControl類(lèi)
主要原因是WebControl類(lèi)公共的東西比Control類(lèi)
2.TagKey
表示控件的標(biāo)簽,默認(rèn)情況下為﹤span﹥,可以重寫(xiě)此屬性修改或者重寫(xiě)WebControl類(lèi)的構(gòu)造函數(shù)
3.AddAttributesToRender方法
為標(biāo)簽添加屬性和樣式
4.RenderContents方法
在標(biāo)簽內(nèi)呈現(xiàn)內(nèi)容
如果控件不復(fù)雜,則可直接從標(biāo)準(zhǔn)控件繼承(如label),再根據(jù)需要擴(kuò)展,重寫(xiě)AddAttributesToRender方法,還可以重寫(xiě)
TagKey更改默認(rèn)標(biāo)簽,而無(wú)須重寫(xiě)RenderContents方法.如果控件比較復(fù)雜,不是單一的,則需要在RenderContents方法輸出控件的內(nèi)部的內(nèi)容.
其實(shí)最大的區(qū)別就是默認(rèn)情況下WebControl類(lèi)為你加了一個(gè)標(biāo)簽,方便添加WebControl類(lèi)的一些公共的東西,如果你重寫(xiě)Render()方法,而舍棄RenderContents方法,你就無(wú)福享受WebControl類(lèi)給你提供的這么多屬性和方法了.
大家多熟悉下WebControl類(lèi)的一些公共屬性,然后再多改改,可以明白的更加深刻.
我喜歡慢慢的把東西全講全,不然心里不舒服,所以我就慢慢寫(xiě)了,當(dāng)然前提是我理解的基礎(chǔ)上.這次的例子,大家可根據(jù)第二篇的代碼適當(dāng)修改就可.錯(cuò)誤之處還請(qǐng)指出^_^
ASP.NET控件開(kāi)發(fā)之RenderContents使用就向你介紹到這里,希望對(duì)你了解ASP.NET控件開(kāi)發(fā)基礎(chǔ)之RenderContents使用有所幫助。
【編輯推薦】