掌握伺服器控件生命週期是開發高品質自訂控件的基石。本文系統梳理 10 個階段,並提供完整可運行的控件範例驗證流程。
OnInit):遞迴遍歷子控件呼叫 OnInit,開啟視圖狀態追蹤 (TrackViewState),回發時才能正確還原屬性值。LoadViewState):僅回發時執行,將視圖狀態載入控件。首次訪問無狀態資料。LoadPostData):回發時執行,實作 IPostBackDataHandler。參數 NameValueCollection 裝載客戶端提交資料,比較新舊值決定是否觸發 RaisePostDataChangedEvent。OnLoad):呼叫 Page_Load 後依序呼叫各控件 OnLoad。RaisePostDataChangedEvent):回發時執行,資料變更時 (LoadPostData 回傳 true) 觸發。RaisePostBackEvent):回發時處理引起回發的客戶端事件,透過參數判斷觸發源控件執行對應邏輯。實作 IPostBackEventHandler。OnPreRender):渲染前準備,如註冊 JavaScript、隱藏欄位等。SaveViewState):儲存控件視圖資訊。首次請求也執行。Render):輸出控件標記與文字至輸出流。OnUnload):資源清理。建立控件庫專案 + 網站專案,引用後拖放測試:
namespace ControlLibrary {
[DefaultProperty("Text")]
[ToolboxData("<{0}:ControlLifecycle runat=server></{0}:ControlLifecycle>")]
public class ControlLifecycle : WebControl, IPostBackDataHandler, IPostBackEventHandler {
protected override void OnInit(EventArgs e) {
OutPut("1.OnInit");
base.OnInit(e);
this.Page.RegisterRequiresPostBack(this);
}
protected override void LoadViewState(object savedState) {
OutPut("2.LoadViewState");
base.LoadViewState(savedState);
}
public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection) {
OutPut("3.LoadPostData");
return true;
}
protected override void OnLoad(EventArgs e) {
OutPut("4.OnLoad");
base.OnLoad(e);
}
public virtual void RaisePostDataChangedEvent() {
OutPut("5.RaisePostDataChangedEvent");
}
public virtual void RaisePostBackEvent(string eventArgument) {
OutPut("6.RaisePostBackEvent");
}
protected override void OnPreRender(EventArgs e) {
OutPut("7.OnPreRender");
base.OnPreRender(e);
}
protected override object SaveViewState() {
OutPut("8.SaveViewState");
base.SaveViewState();
return new Pair();
}
protected override void Render(HtmlTextWriter writer) {
writer.Write("<INPUT type=button name=\"{0}\" value=\"Click Me!\" onclick=\"{1}\">",
this.UniqueID, Page.ClientScript.GetPostBackEventReference(this, ""));
OutPut("9.Render");
base.Render(writer);
}
private void OutPut(string strText) {
if (!this.DesignMode)
HttpContext.Current.Response.Write(strText + "<br>");
}
}
}
| 基類 | 適用場景 |
|---|---|
Control | 所有控件根基類,提供通用屬性/方法 |
WebControl | 繼承 Control,增加佈局、無障礙、外觀樣式特性 |
CompositeControl | 聚合現有控件建立組合控件,預設實作 INamingContainer |
RenderControl → Render → RenderBeginTag、RenderContents、RenderEndTag
RenderBeginTag/RenderEndTag:可覆寫,預設 <span></span>,定義控件起始/結束標記RenderContents:輸出控件內容了解生命週期最佳途徑:親手開發一個控件。後續將深入探討進階控件開發主題。