Page类与Control类的生命周期(life cycle)比较总结[转]

最近一段時間在使用Microsoft SharePoint2007,進行開發一個Document 管理系統,裡面有使用SharePoint Designer設計Page佈局,需要使用自定義開發的Webpart 控件,由於本來就沒有進行搞控件開發了,再加上有句名言“知識就是力量”,那沒得知識就沒得力量了,所以沒得辦法,就利用Baidu + Google,googling了半下午。結果再次驗證了Google< /SPAN>的搜索實力確實比Baidu強悍啊,在此為Google最近的決定感到失望,牢騷就不多發了,還是進正題。以下是自己的一些新的總結和找到的一些學習資源。希望可以share.

首先了解到,Page類繼承自模板控件類TemplateControl Http 處理程序接口IHttpHandler

1.TemplateControl類是個abstract類,繼承自Control類,ID命名容器控件INamingContainer,

和設備篩選器接口IFilterResolutionService< SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: 宋體; FONT-SIZE: 9pt">。

2. IHttpHandler接口是為了使用Http處理程序同步處理Http Web請求而實現的協定。有一個只SetIsReusable屬性和一個方法ProcessRequest(HttpContext context)方法,用來處理Http Web請求。

     既然Page間接的繼承自Control類,那下面就先從介紹Control類說起。

Control類的生命週期有七個大的事件階段,分別為Init事件,< SPAN style="LINE-HEIGHT: 18px">Load事件,DataBinding事件,PreRender 事件,Render方法,Unload事件,Disposed事件。下面簡單介紹下每個階段;

1.Init階段,引發Init事件,執行OnInit(EventArgs e)虛方法。詳細請參見處理繼承的事件。

2.然後執行TrackViewState(object savedState)虛方法,會根據頁面IsPostBack屬性,來確定是否LoadViewState< /SPAN>請參見處理回發數據維護控件中的狀態(objcet savedState)來加載視圖狀態,以及如果控件繼承自接口IPostBackDataHandler,還會實現< STRONG>LoadPostData(string postDataKey,System.Collections.Specialized.NameValueCollection postCollection), 來處理回發數據。詳細

3.Load階段,引發Load事件,執行OnLoad(EventArgs e)虛方法。此時,Load事件樹中的服務器控件已創建並初始化、狀態已還原並且窗體控件反映了客戶端的數據。詳細參見 處理繼承的事件。

4.之後根據頁面IsPostBack屬性,如果實現了接口IPostBackDataHandler則調用RaisePostDataChangedEvent() 方法,來處理引發更改事件以響應當前和以前回發之間的狀態更改。如果實現如果已實現 IPostBackEventHandler接口,則引發 RaisePostBackEvent(string eventArgument)方法的實現來處理,來處理引起回發的客戶端事件,並在服務器上引發相應的事件。 詳細參見< SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: 宋體">處理回發數據 捕獲回發事件。

5.PreRender階段,引發PreRender  事件,執行OnPreRender< /SPAN>方法,在呈現輸出之前執行任何更新。可以保存在預呈現階段對控件狀態所做的更改,而在呈現階段所對的更改則會丟失。此階段是對控件做任何更新的最後機會。詳細請參見處理繼承的事件。 (EventArgs e)

6.SaveViewState階段,在此階段後,自動將控件的 View State 屬性保持到字符串對像中。此字符串對像被發送到客戶端並作為隱藏變量發送回來。為了提高效率,控件可以重寫 SaveViewState()  方法以修改 View State屬性。 詳細請參見 維護控件中的狀態。

7.呈現Render階段,此階段沒有不適事件,執行Render()方法,來生成呈現給客戶端的輸出。 詳細參見< SPAN style="LINE-HEIGHT: 18px; COLOR: #000000">呈現 ASP.NET 服務器控件< /SPAN>方法,以便動態設置區域性信息。注意,在使用 Page_事件語法創建事件處理程序時,將隱式調用基實現,因此無需在方法中調用它。例如,無論是否創建 Page_Load 方法,始終都會調用頁基類的 OnLoad 方法。但是,如果使用 override 關鍵字(在 Visual Basic 中為 Overrides< /SPAN>)重寫頁的 OnLoad 方法,則必須顯式調用基方法。例如,如果在頁中重寫  OnLoad 方法,則必須調用 base.Load(在 Visual Basic 中為 MyBase.Load)以運行基實現

8.Dispose階段< /SPAN>,執行Disponse( )方法,執行銷毀控件前的所有最終清理操作。在此階段必須釋放對昂貴資源的引用,如數據庫鏈接。 詳細參見< SPAN style="LINE-HEIGHT: 18px; COLOR: #000000">ASP.NET 服務器控件中的方法方法(並調用 base.OnEventName )。

9.卸載Unload< /STRONG>階段,引發Unload事件,執行OnUnload()方法,來執行銷毀控件前的所有最終清理操作。控件作者通常在 Dispose  中執行清除,而不處理此事件。

 

以下2點要有所注意:   

1.要重寫 Event Name  事件,請重寫 < SPAN style="LINE-HEIGHT: 18px">OnEventName 

2.之上的方法和事件基本在自己創建控件時都可以重寫 System.Web.UI.Controlabstract方法,但可以看出以下幾個除外:LoadPostData 和 RaisePostDataChangedEvent 是 IPostBackDataHandler 接口的方法,而 RaisePostBackEvent 屬於  IPostBackEventHandler 接口。如果控件參與回發數據處理,則必須實現 IPostBackDataHandler。如果控件收到回發事件,則必須實現 IPostBackEventHandler

3.以上沒有列出 CreateChildControls 方法,這是由於每當 ASP.NET 頁框架需要創建控件樹時就會調用該方法,且該方法調用並不限於控件生命週期的特定階段。例如,可以在加載頁時、在綁定數據過程中或者在呈現過程中調用 CreateChildControls,以及在動態創建控件的時候也可以調用的。

下面給個自己創建個WebPart控件示範,功能比較簡單,在頁面上面實現Ifame實現內嵌頁面的效果。

 

view plaincopy to clipboardprint?
  1. using  System;  
  2. using System.Collections.Generic;  
  3. using  System.Text;  
  4. using System.Web;  
  5. using  System.Web.UI;  
  6. using System.Web.UI.HtmlControls;  
  7. using  System.Web.UI.WebControls.WebParts;  
  8.   < /LI>
  9. namespace  IframeWebpart  
  10. {  
  11.     public class  Iframe:WebPart,INamingContainer  
  12.     {   
  13.          private int _width = 100;  
  14.       ;   private int _height = 100;  
  15.          private HtmlTableCell _htc = new HtmlTableCell();  ; 
  16.       ;   private string _url = @" http://www.baidu.com";  < /SPAN> Request 實例包括的任何回發數據,如果需要在 Load  事件之前對頁或控件執行處理,請使用該事件。
  17.   
  18.       ;   [WebBrowsable(true),Personalizable(true)]   
  19.          public int IWidth  
  20.       ;   {  
  21.              get { return _width ; }  
  22.       ;       set< /SPAN> { _width = value; }  
  23.          }  
  24.   < /LI>
  25.          [WebBrowsable(true),Personalizable(true)]  
  26.       ;   public int IHeight  
  27.          {  
  28.       ;       get< /SPAN> { return _height; }  
  29.              set { _height = value; }  
  30.       ;   }  
  31.   
  32.       ;   [WebBrowsable(true), Personalizable(true)]   
  33.          public string Url  
  34.       ;   {  
  35.              get { return _url ; }  
  36.       ;       set< /SPAN> { _url = value; }  
  37.          }  
  38.   < /LI>
  39.          protected override void CreateChildControls( )  
  40.       ;   {  
  41.              //base.CreateChildControls();< SPAN style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 18px; BORDER-RIGHT-STYLE: none; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER- TOP-STYLE: none; COLOR: black; BORDER-LEFT-STYLE: none; PADDING-TOP: 0px">  
  42.       ;       this< /SPAN>.Controls.Add(new LiteralControl("<table>"+"/n"));  
  43.              this.Controls.Add(new LiteralControl ("<td>"+"/ n"));  
  44.       ;       this< /SPAN>.Controls.Add(this._htc);  
  45.              this.Controls.Add(new LiteralControl ("</td>"+" /n"));  
  46.       ;       this< /SPAN>.Controls.Add(new LiteralControl("</table>"+"/n"));  < /SPAN>
  47.              if (!this.Page.IsPostBack )  
  48.       ;       {  
  49.                  this.AddControls();  < /LI>
  50.       ;       }  
  51.   
  52.       ;   }  
  53.   
  54.       ;   protected override void OnLoad(EventArgs e)  
  55.          {  
  56.       ;       base< /SPAN>.OnLoad(e);  
  57.              //if (!this.Page.IsPostBack)< /SPAN>  
  58.       ;       //{< SPAN style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 18px; BORDER-RIGHT-STYLE: none; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER- TOP-STYLE: none; COLOR: black; BORDER-LEFT-STYLE: none; PADDING-TOP: 0px">  
  59.              //    this.AddControls ();  
  60.       ;       //}< SPAN style="BORDER-BOTTOM-STYLE: none; PADDING-BOTTOM: 0px; LINE-HEIGHT: 18px; BORDER-RIGHT-STYLE: none; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; BORDER- TOP-STYLE: none; COLOR: black; BORDER-LEFT-STYLE: none; PADDING-TOP: 0px">  
  61.          }  
  62.   < /LI>
  63.          protected override void Render( HtmlTextWriter writer)  
  64.       ;   {  
  65.              base.Render(writer);  
  66.       ;   }  
  67.   
  68.       ;   private void AddControls()  
  69.          {  
  70.       ;       this< /SPAN>._htc.Controls.Add(new LiteralControl("<iframe id='iframe1'  src=""+this.Url+"" mce_src=""+this.Url+"" width='"+this.IWidth+< /SPAN>"' height='"+this.IHeight+"'  marginheight='0' frameborder='0' scrolling='no' vspace='0'  hspace='0'  marginwidth='0'  >"+"/n"));  

     

     

     

    Control類的比較簡單,下面介紹Page類,Page類的生命週期相對control要稍微複雜一些。 (下面介紹參考了 MSDN上面的介紹)

    普通的常規頁面生命週期有:頁請求,開始階段,初始化,加載,驗證,回發事件處理,呈現,卸載,除了頁生命週期階段以外,在請求前後還存在應用程序階段,但是這些階段並不特定於頁。以下詳細介紹;

    1頁請求:發生在頁面生命週期之前,用戶請求頁時,ASP.NET將確定是否需要分析和編譯頁,從而確定是否開始頁面的生命週期,或者是否可以在不運行頁的情況下發送頁面緩存以進行響應。

    2開始:設置頁屬性,如:HttpContext以及其他屬性;在此階段,頁面需要確定是回發請求還是新請求,並設置IsPostBack屬性;設置頁面的UICulture屬性。

    3頁面初始化:加載所有主題;控件生成,並設置UniqueID

    注:ViewStateControlState中的值還未加載至控件;如果頁面是回發,則回發數據也還未加載;故此時控件可以訪問,但值可能出錯。

    4加載:如果當前請求是回發請求,則為控件加載ViewStateControlState中的值。

    5驗證:調用所有驗證程序控件的Validate方法,此方法將設置驗證程序控件和頁的IsValid屬性。

    6回發事件處理:如果請求是回發請求,則調用所有事件處理程序。

    7呈現:首先對該頁和所有控件進行保存視圖狀態,然後對每個控件調用Render方法,它會提供一個文本編寫器,用於將控件的輸入寫入頁的Response屬性的OutputStream< /SPAN>中。

    8卸載:完成呈現,並已將頁發送至客戶端、準備丟棄該頁後,調用卸載。將卸載屬性如:ResponseRequest等等,故之後如果在調用這些對象,都將出錯異常的。

     

    在介紹Asp.net之前先來看兩張關於頁面的請求過程圖片:

     

     

     

     

    第一張是個普通的頁面請求過程

    第二張是個是個添加的Button按鈕控件PostBack後的頁面請求過程。

     

    比較這兩張圖片可以很清晰的得出以下兩點內容。

    一.  Asp.Net的頁面生命週期,基本都有如下幾個階段;

    < SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: Century; FONT-SIZE: 9pt">PreInit

    < SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: Century; FONT-SIZE: 9pt">Init

    < SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: Century; FONT-SIZE: 9pt">InitComplete

    < SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: Century; FONT-SIZE: 9pt">PreLoad

    < SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: Century; FONT-SIZE: 9pt">Load

    < SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: Century; FONT-SIZE: 9pt">LoadComplete

    < SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: Century; FONT-SIZE: 9pt">PreRender

    < SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: Century; FONT-SIZE: 9pt">Render

    < SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: Century; FONT-SIZE: 9pt">RenderComplete

    < SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: Century; FONT-SIZE: 9pt">SaveState

    < SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: Century; FONT-SIZE: 9pt">SaveStateComplete

    < SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: Century; FONT-SIZE: 9pt">Render

    < SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: Century; FONT-SIZE: 9pt">UnLoad

    二. 在頁面的響應生命週期階段,控件的生命週期階段也在相應同步進行著。

     

    下面也來個粗略的介紹;

    1.      PreInit階段

    此階段引發PreInit事件,執行OnPreInit()方法,完成的操作,有比如查IsPostBack屬性來確定是

    Theme屬性,讀取或設置配置文件屬性。注:如果請求是回發請求,則控件的值尚未從視圖狀態恢復,即:不應該在此事件中設置控件屬性。

    2.      Init階段

    在所有控件都已初始化,且應用了外觀後由里到外引發 Init事件,執行由自Control類繼承得 OnInit()方法,使用該事件來讀取或初始化控件屬性。

    3.      InitComplete階段

    Page對象引發。使用該事件來處理要求先完成所有初始化工作的任務。執行OnInitComplete()方法。

    4.  PreLoad< /STRONG>

     Page 引發該事件後,執行OnPreLoad(),< SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: 新宋體; FONT-SIZE: 9pt">它會為自身和所有控件加載視圖狀態,然後會處理

    5.  Load< /STRONG>

    PagePage上調用OnLoad事件方法,然後以遞歸方式對每個子控件執行相同操作,如此循環往復,直到加載完本頁和所有控件為止。使用OnLoad()事件方法來設置控件中的屬性並建立數據庫連接。

    6.  控件事件

    使用這些事件來處理特定控件事件,如 Button 控件的 Click< /SPAN> 事件等。注:在回發請求中,如果頁包含驗證程序控件,請在執行任何處理之前檢查 Page和各個驗證控件的IsValid屬性。 開發自定義 ASP.NET  ;服務器控件。用戶

    7.      LoadComplete

    引發LoadComplete事件,執行OnLoadComplete()方法,對需要加載頁上的所有其他控件的任務使用該事件。

    8.      PreRender

    引發PreRender事件,執行由Control類繼承來的OnPreRender()方法,使用該事件對頁或其控件的內容進行最後更改。注:在該事件發生前的操作:Page對所有控件遞歸進行EnsureChildControl操作設置了DataSourceID屬性的數據綁定控件會調用DataBind方法。

    9.  PreRenderComplete< /STRONG>

       引發 PreRenderComplete事件,執行的On PreRenderComplete方法。

    10.  SaveStateComplete
    引發SaveStateComplete事件,執行由OnSaveStateComplete(EventArgs e)方法,在該事件發生前,

    已針對頁和所有控件保存了ViewState。將忽略此時對頁或控件進行的任何更改。 。

    11Render
    這不是事件;在處理的這個階段,Page 對象會在每個控件上調用此方法。所有 ASP.NET Web 服務

    器控件都有一個用於寫出發送給瀏覽器的控件標記的 Render 方法。如果創建自定義控件,通常要重寫此

    方法以輸出控件的標記。不過,如果自定義控件只合併標準的 ASP.NET Web < SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: 新宋體; FONT-SIZE: 9pt">服務器控件,不合併自定

    義標記,則不需要重寫 Render < SPAN style="LINE-HEIGHT: 18px; FONT-FAMILY: 新宋體; FONT-SIZE: 9pt">方法。有關更多信息,請參見

    控件(.ascx 文件)自動合併呈現,因此不需要在代碼中顯式呈現該控件

    12.Unload

    引發Unload事件,執行由Control類繼承來的OnUnLoad()方法,對子控件由里向外執行此方法。

     

    注意點。當從 Page  ;類繼承類時,除了可以處理由頁引發的事件以外,還可以重寫頁的基類中的方法。例如,可以重寫頁的 < SPAN style="LINE-HEIGHT: 18px; COLOR: #000000">InitializeCulture 

     

    以上就是本人的理解和總結,比較簡單,可以說只有的理解了簡單Control類和Page類的通用生命週期,以後才可以分析複雜的問題,比如動態創建控件時的數據丟失問題等。再比如目前有不少人喜歡在開發Web時候,比較喜歡直接讓新建的Page頁面繼承自Page類,在這個繼承來里面來寫一些實現用戶身份驗證功能,但是如果對頁面的生命週期比較了解後,可以這樣來做,首先寫個繼承自Page類的類,在這個類裡面根據需要來重寫abstract方法和寫一些通用的用戶身份驗證方法,之後讓自己的頁面後台代碼類來實現這個類,從而達到通用的效果。這樣做對代碼復用性的提高,大家覺得是否有幫助呢?

     

    以上拙見,如有錯誤之處,請幫忙指教。

     

     

    參考資料

    1.        MSDN文檔ASP.NET 頁生命週期概述

    2.        《庖丁解牛:縱向切入ASP.NET 3.5控件和組件開發技術》

    3.       Programming ASP.NET 》學習筆記(控件)

    4.   ;     SnowQuery的專欄

    5.   ;     深入理解Asp.net動態控件

  71.              this._htc.Controls.Add(new  ;LiteralControl("</iframe>"+"/n"));           
  72.       ;   }  
  73.   
  74.     }   
  75. }  
  76. < /OL>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值