控件生命周期
1.初始化(對應Oninit方法)
這裡頁面通過ProcessRequest方法來遞歸遍歷它的子控件(即頁面中的空間,其實頁面也算控件)。使子控件依次調用它們的Oninit方法。 我們這裡可以重寫控件的OnInit方法,來擴展控件功能或增加初始化內容。在本階段還要打開視圖狀態跟蹤功能,調用TrackviewState方法, 這樣存儲在viewState對象裡面的值在頁面回發時才能正確灰復到控件屬性中。
2.加載視圖狀態(對應LoadViewState方法)
本階段僅在頁面回發時才執行,加載視圖狀態到控件。在第一次訪問頁面時我們還沒有獲得存儲到視圖狀態的狀態數據。
3.加載回傳數據(對應LoadPostData方法)
在頁面回發時執行。LoadPostData實現IPostBackDataHandler(實現控件數據回傳必須要繼承該接口)的一個方法,該方法參數 NameValueCollection類型的對象裝載了客戶端提交的數據。另外該方法還會比較控件的舊值和新值返回一個bool類型值,以決定是否執行 RaisePostDatachangedEvent方法。
客戶修改窗體數據進行提交後,接收到的投遞的數據是以 “&”符號隔開的一些鍵值串,頁面處理器將投遞的數據集合名稱與頁面控件 的ID一一匹配,根據匹配ID檢索對應的服務器控件有沒有實現 IPostBackDataHandler接口,如果實現了就調用控件的LoadPostData方法,給控 件刷新其值。
4.裝載(對應OnLoad方法)
頁面裝載時調用Page_Load()事件,在依次調用各個控件OnLoad方法.
5.數據回傳事件通知(對應RaisePostDataChangeEvent方法)
在頁面回發時執行。該方法也實現了IPostBackDataHandler接口。當bool值為true代表數據更改了,就執行該方法。
6.觸發回發事件(對應RaisePostBackEvent方法)
在頁面回發時執行。主要是處理引起回發的客戶端事件,成功捕獲回發的客戶端事件進行服務器端的相應處理。也實現了 IPostBackDataHandler接口。可以通過本法的參數來判斷是哪個控件觸發的回發事件,進而執行不同的事件處理邏輯。
7.預呈現(對應OnPreRender方法)
主要完成呈現(Render方法)之前所需要的一些處理。如注冊JavaScript腳本和隱藏域控件等。
8.保存視圖狀態(對應SaveViewState方法)
該方法是把頁面控件視圖信息進行存儲。第一次請求該頁面就會執行該操作。
9.呈現(對應Render方法)
主要將控件標記和字符文本輸出到服務器控件輸出流中。
10.卸載(對應OnUnload方法)
對控件資源清除工作。
可以通過構造一個簡單的服務器控件來熟悉它的生命周期
先創建一個控件庫(新建項目選擇ASP.NET服務器控件)和一個網站,再在類庫中添加一個類(添加新建項選擇ASP.NET 服務器控件)。在 講下列代碼復制到類庫中去。在生成該類庫並在網站中引用該類庫,再在該在網站上新建一個aspx文件,在頁面工具箱中直接將控件拖到頁面 上即可。
代碼
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Linq;
5 using System.Text;
6 using System.Web;
7 using System.Web.UI;
8 using System.Web.UI.WebControls;
9 using System.Collections.Specialized;
10
11 namespace ControlLibrary
12 {
13 [DefaultProperty("Text")]
14 [ToolboxData("<{0}:ControlLifecycle runat=server></ {0}:ControlLifecycle>")]
15 public class ControlLifecycle : WebControl,IPostBackDataHandler,IPostBackEventHandler
16 {
17 protected override void OnInit(EventArgs e)
18 {
19 //輸出
20 OutPut ("1.OnInit");
21 base.OnInit(e);
22 //注冊
23 this.Page.RegisterRequiresPostBack(this);
24 }
25
26 protected override void LoadViewState(object savedState)
27 {
28 OutPut ("2.LoadViewState");
29 base.LoadViewState(savedState);
30
31 }
32
33 public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)
34 {
35
36 OutPut("3.LoadPostData");
37 return true;
38 }
39
40 protected override void OnLoad(EventArgs e)
41 {
42 OutPut("4.OnLoad");
43 base.OnLoad(e);
44 }
45
46 public virtual void RaisePostDataChangedEvent()
47 {
48 OutPut("5. RaisePostDataChangedEvent");
49 }
50
51 public virtual void RaisePostBackEvent(string eventArgument)
52 {
53 OutPut("6. RaisePostBackEvent");
54 }
55
56 private void OutPut(string strText)
57 {
58 if (this.DesignMode == false)
59 {
60 HttpContext.Current.Response.Write(strText + "<br>");
61 }
62 }
63
64 protected override void OnPreRender(EventArgs e)
65 {
66 OutPut("7. OnPreRender");
67 base.OnPreRender(e);
68 }
69
70 protected override object SaveViewState()
71 {
72 OutPut("8. SaveViewState");
73 base.SaveViewState();
74 return new Pair();
75 }
76
77 protected override void Render(HtmlTextWriter writer)
78 {
79 writer.Write("<INPUT type=button name=\"{0}\" value=\"Click Me!\" style='position:absolute; left: 20; top: 280px' onclick=\"{1}\">", this.UniqueID, Page.ClientScript.GetPostBackEventReference(this, ""));
80 OutPut("9. Render");
81 base.Render(writer);
82 }
83
84 }
85 }
86
其實上面過程就算是我們開發了一個控件。了解它,最好的辦法是嘗試去開發它。
開發一個控件首先要選好它要繼承的基類
選擇基類
Control
控件開發基類,所有控件都直接或間接繼承該類。提供了各類控件通用的屬性和方法。
WebControl
webcontrol繼承了control所有的屬性,還增加了布局,可訪問性,外觀樣式等特性。
CompositeControl
如果把現有控件聚合起來創建一個組合控件時,可以繼承此類。該類默認實現了INamingContainer接口。
控件呈現順序
上面介紹到了控件Render階段主要是將控件標記和字符文本輸出到服務器控件流當中。這裡可以直接寫HTML標記(上面例子就是的)也可以 調用每個控件都有的RenderControl方法到輸出流。在WebControl中,介紹以下5個函數
RenderControl(HtmlTextWriter writer)
Render(HtmlTextWriter writer)
RenderBeginTag(HtmlTextWriter writer)
RenderContents(HtmlTextWriter writer)
RenderEndTag(HtmlTextWirter writer)
在RenderControl 會內部調用Render,在Render會內部調用RenderBeginTag,RenderContents,RenderEndTag。
其中RenderBeginTag,RenderEndTag可以重寫,默認值為<span></span>。它們是用來定義控件起始和結束的標記。 RenderContents看英文的意思就明白了。(待續)