asp.net控件開發基礎(4)

作者: Clingingboy  來源: 博客園  發布時間: 2010-10-02 19:20  閱讀: 1092 次  推薦: 0   原文鏈接   [收藏]  

  一.從繼承WebControl開始

  在第二篇教程中,重點介紹了Render()方法的使用,用來呈現控件,但從Control類繼承的控件尚未發揮asp.net控件的作用.大家知道web服務器控件分為HTML服務器控件(如<input id="Button2" runat="server" type="button" value="button" />這樣的形式)和標準服務器控件(就是<asp:..  id="" runat="server" />這樣的形式的控件)。

  HTML服務器控件的控件從System.Web.UI.HtmlControls.HtmlControl 類派生,標準服務器控件的控件從System.Web.UI.WebControls.WebControl 類派生,HtmlControl 類和WebControl 類則從System.Web.UI.Control 類派生,并擴展。

  所以我們說,所有的服務器控件都繼承自System.Web.UI.Control 類,即所有的服務器控件都具有Control 類的共同屬性,如Visible,EnableViewState屬性,HtmlControl 類和WebControl 類則擴充了System.Web.UI.Control 類的功能,如HtmlControl 類定義了所有 HTML 服務器控件所通用的方法、屬性 (Property) 和事件(具體參數參照MSDN),WebControl 類定義了所有 標準服務器控件所通用的方法、屬性 (Property) 和事件(具體參數參照MSDN)。

  如每個繼承了WebControl 類的標準控件都有定義外觀和行為的屬性,然后不同控件再根據需要擴展功能.

  圖一

  所以我們推薦的做法是直接從WebControl 類派生,而非Control類.我們所做的非并從頭開始.從WebControl 類繼承可以幫我們省很多工作.

  二.重寫WebControl類方法,不再是Render()

  WebControl類繼承了Control類,當然有Render方法,在WebControl類中重寫了Render方法,如下代碼
  示例一

 

 
protected override void Render(HtmlTextWriter output)
{
 RenderBeginTag(output);
 RenderContents(output);
 RenderEndTag(output);
}

 

  注意 RebderBeginTag方法并非是HtmlTextWriter類中的方法,而是WebControl類中的方法,表示輸出HTML標簽頭標記,如<table .....>,RenderEndTag方法則輸出HTML標簽尾標記,如</table>.中間的RenderContents方法則就是Control類的Render方法. 看下面RenderContents方法的定義.
  示例二

 
protected override void RenderContents(HtmlTextWriter output){
 
//使用默認邏輯來呈現子控件,那么一定要調用基類中的方法。
 base.Render(output);
}

  接著再看RenderBeginTag方法的定義
  示例三

 
public virtual void RenderBeginTag(HtmlTextWriter output)
{

//添加呈現控件的屬性和樣式
//AddAttributesToRender為WebControl類中的方法
AddAttributesToRender(output);
//呈現控件標簽
//如label控件呈現<span >
//textbox控件呈現<input >
HtmlTextWriterTag tagKey = TagKey;
if (tagKey != HtmlTextWriterTag.Unknown)
{
output.RenderBeginTag(tagKey);
}

else
{
output.RenderBeginTag(
this.TagName);
}
}

  這里打個比方,假設你要輸出一個表格,你就必須定義<table>標簽頭,然后在其內部定義<tr>,<td>,下面看Control類中Render方法的實現,表明Render方法必須完成所有的任務,包括標簽頭標記<table>和<table>標簽的屬性和樣式的輸出.
  示例四

 
protected override void Render(HtmlTextWriter writer)
{

//為table標簽定義屬性和樣式
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類中重寫了Render方法后,直接幫你定義好了標簽,默認情況下為<span>,可通過重寫TagKey屬性來修改標簽,然后AddAttributesToRender方法為標簽定義樣式和屬性
  示例五

 
protected override HtmlTextWriterTag TagKey
{

get { return HtmlTextWriterTag.Table; }
}

  示例六

 
protected override void AddAttributesToRender(HtmlTextWriter writer)
{

//為table標簽定義屬性和樣式
writer.AddAttribute(HtmlTextWriterAttribute.Width, "287px");
writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth,
"0");

base.AddAttributesToRender(writer);

}

  接著重寫RenderContents方法,對比上面的Render方法,實現效果是一樣的
  示例七

 
protected override void RenderContents(HtmlTextWriter writer)
{

//注意,此處無沒有table標簽,只定義其內部標簽
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);

//以下省略

}

  所以說重寫后的Render方法在默認情況下加了一個標簽,而你可以重寫這個標簽(默認情況下為<span>).可能大家對其感到奇怪,即然可以實現同樣效果,有必要重寫Render方法,再加一個RenderContents方法嗎?
  三.Render方法和RenderContents方法的區別
  當你繼承WebControl類,在RenderContents方法中實現示例四代碼時,(我們再以以前的例子展示)呈現后的代碼如下,看到沒有,控件ID為<span>。在RenderContents方法輸入的標簽將成為其內部標簽.再看看這個控件的屬性面板,你會看到很多的繼承自WebControl類的屬性,設置其屬性,即是設置<span>標簽的屬性.TagKey的作用大概就在于此吧,為了使用WebControl類的公共屬性,而非定義在<table>標簽上。
  示例八

 
<span id="CreditCardForm5_1"><table style="border-width:0;">
<tr>
<td><strong>信用卡類型</strong></td><td><select name="PaymentMethod" id="PaymentMethod" style="width:100%;">
......

  假設我們稱<span>里面的<table>等標簽為子標簽,在RenderContents方法應該定義控件的子標簽,如果你只定義標簽屬性的話,只需重寫AddAttributesToRender方法即可,可不須重寫RenderContents方法。
  下面再講下重寫標簽的方法

  (1) 重寫TagKey屬性,下面重寫label控件的標簽

 
public class Ch4Label: Label
{

protected override HtmlTextWriterTag TagKey
{

get { return HtmlTextWriterTag.Div; }
}
}

  (2)重寫基類構造函數,此方法只有在繼承Control類后適用

 
public CreditCardForm5() : base(HtmlTextWriterTag.Table) { }

   如果控件不復雜,則可直接從標準控件繼承(如label),再根據需要擴展,重寫AddAttributesToRender方法,還可以重寫TagKey更改默認標簽,而無須重寫RenderContents方法.如果控件比較復雜,不是單一的,則需要在RenderContents方法輸出控件的內部的內容。

  其實最大的區別就是默認情況下WebControl類為你加了一個標簽,方便添加WebControl類的一些公共的東西,如果你重寫Render()方法,而舍棄RenderContents方法,你就無福享受WebControl類給你提供的這么多屬性和方法了。

  大家多熟悉下WebControl類的一些公共屬性,然后再多改改,可以明白的更加深刻,我喜歡慢慢的把東西全講全,不然心里不舒服,所以我就慢慢寫了,當然前提是我理解的基礎上.這次的例子,大家可根據第二篇的代碼適當修改就可.錯誤之處還請指出。

上一篇:asp.net控件開發基礎(3)

下一篇:asp.net控件開發基礎(5)
0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()