上一篇寫了有關回傳的一些東西,這次我本來不知道該寫什麼的,因為各方面的關聯太多了,最後我還是想,還是慢慢一點點的寫吧.這次講WebControl
一.從繼承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) { }
最後總結下:
1.控制項繼承自WebControl類 主要原因是WebControl類公用的東西比Control類
2.TagKey 表示控制項的標籤,預設情況下為<span>,可以重寫此屬性修改或者重寫WebControl類的建構函式
3.AddAttributesToRender方法 為標籤添加屬性和樣式
4.RenderContents方法 在標籤內呈現內容
如果控制項不複雜,則可直接從標準控制項繼承(如label),再根據需要擴充,重寫AddAttributesToRender方法,還可以重寫
TagKey更改預設標籤,而無須重寫RenderContents方法.如果控制項比較複雜,不是單一的,則需要在RenderContents方法輸出控制項的內部的內容.
其實最大的區別就是預設情況下WebControl類為你加了一個標籤,方便添加WebControl類的一些公用的東西,如果你重寫Render()方法,而捨棄RenderContents方法,你就無福享受WebControl類給你提供的這麼多屬性和方法了.
大家多熟悉下WebControl類的一些公用屬性,然後再多改改,可以明白的更加深刻.
我喜歡慢慢的把東西全講全,不然心裡不舒服,所以我就慢慢寫了,當然前提是我理解的基礎上.這次的例子,大家可根據第二篇的代碼適當修改就可.錯誤之處還請指出^_^
參考文章:http://dev.yesky.com/msdn/37/2416037.shtml
此文章轉自:http://www.cnblogs.com/Clingingboy/archive/2006/08/05/468694.html