首页 > 代码库 > asp.net页面事件执行顺序

asp.net页面事件执行顺序

转自http://www.cnblogs.com/hnlyh/articles/4230388.html

C#代码 

  1. using System;  
  2. using System.Data;  
  3. using System.Configuration;  
  4. using System.Web;  
  5. using System.Web.Security;  
  6. using System.Web.UI;  
  7. using System.Web.UI.WebControls;  
  8. using System.Web.UI.WebControls.WebParts;  
  9. using System.Web.UI.HtmlControls;  
  10.   
  11. public partial class _Default : Page   
  12. {  
  13.     protected void Page_Load(object sender, EventArgs e)  
  14.     {  
  15.   
  16.     }  
  17.  
  18.     #region OnPreInit 第一步  
  19.     protected override void OnPreInit(EventArgs e)  
  20.     {  
  21.         //检查 IsPostBack 属性来确定是不是第一次处理该页。  
  22.   
  23.         //创建或重新创建动态控件。  
  24.   
  25.         //动态设置主控页。  
  26.   
  27.         //动态设置 Theme 属性。  
  28.   
  29.         //读取或设置配置文件属性值。  
  30.   
  31.         //注意    
  32.         //如果请求是回发请求,则控件的值尚未从视图状态还原。如果在此阶段设置控件属性,则其值可能会在下一事件中被重写。  
  33.    
  34.   
  35.         base.OnPreInit(e);  
  36.     }  
  37.     #endregion  
  38.  
  39.     #region OnInit 第二步  
  40.     protected override void OnInit(EventArgs e)  
  41.     {  
  42.         //在所有控件都已初始化且已应用所有外观设置后引发。使用该事件来读取或初始化控件属性。  
  43.         base.OnInit(e);  
  44.     }  
  45.     #endregion  
  46.  
  47.     #region OnInitComplete 第三步  
  48.     protected override void OnInitComplete(EventArgs e)  
  49.     {  
  50.         //由 Page 对象引发。使用该事件来处理要求先完成所有初始化工作的任务。  
  51.   
  52.         base.OnInitComplete(e);  
  53.     }  
  54.     #endregion  
  55.  
  56.     #region PreLoad 第四步  
  57.     protected override void OnPreLoad(EventArgs e)  
  58.     {  
  59.         //如果需要在 Load 事件之前对页或控件执行处理,请使用该事件。   
  60.   
  61.         //在 Page 引发该事件后,它会为自身和所有控件加载视图状态,然后会处理 Request 实例包括的任何回发数据。  
  62.   
  63.         base.OnPreLoad(e);  
  64.     }  
  65.     #endregion   
  66.  
  67.     #region OnLoad 第五步  
  68.     protected override void OnLoad(EventArgs e)  
  69.     {  
  70.         //Page 在 Page 上调用 OnLoad 事件方法,然后以递归方式对每个子控件执行相同操作,如此循环往复,直到加载完本页和所有控件为止。  
  71.         //使用 OnLoad 事件方法来设置控件中的属性并建立数据库连接。  
  72.   
  73.         base.OnLoad(e);  
  74.     }  
  75.     #endregion  
  76.  
  77.     #region 控件事件 第六步  
  78.     protected void Button1_Click(object sender, EventArgs e)  
  79.     {  
  80.         //用这些事件来处理特定控件事件,如 Button 控件的 Click 事件或 TextBox 控件的 TextChanged 事件。  
  81.   
  82.         //注意    
  83.         //在回发请求中,如果页包含验证程序控件,请在执行任何处理之前检查 Page 和各个验证控件的 IsValid 属性。  
  84.    
  85.   
  86.     }  
  87.     #endregion  
  88.  
  89.     #region OnLoadComplete 第七步  
  90.     protected override void OnLoadComplete(EventArgs e)  
  91.     {  
  92.         //对需要加载页上的所有其他控件的任务使用该事件。  
  93.   
  94.         base.OnLoadComplete(e);  
  95.     }  
  96.     #endregion  
  97.  
  98.     #region OnPreRender 第八步  
  99.     protected override void OnPreRender(EventArgs e)  
  100.     {  
  101.         //在该事件发生前:  
  102.   
  103.         //Page 对象会针对每个控件和页调用 EnsureChildControls。   
  104.   
  105.         //设置了 DataSourceID 属性的每个数据绑定控件会调用 DataBind 方法。有关更多信息,请参见下面的数据绑定控件的数据绑定事件。  
  106.   
  107.         //页上的每个控件都会发生 PreRender 事件。使用该事件对页或其控件的内容进行最后更改。  
  108.   
  109.         base.OnPreRender(e);  
  110.     }  
  111.     #endregion   
  112.  
  113.     #region SaveStateComplete 第九步  
  114.     protected override void OnSaveStateComplete(EventArgs e)  
  115.     {  
  116.         //在该事件发生前,已针对页和所有控件保存了 ViewState。将忽略此时对页或控件进行的任何更改。  
  117.   
  118.         //使用该事件执行满足以下条件的任务:要求已经保存了视图状态,但未对控件进行任何更改。  
  119.   
  120.         base.OnSaveStateComplete(e);  
  121.     }  
  122.     #endregion  
  123.  
  124.     #region Render 第十步  
  125.     //Render  
  126.     //这不是事件;在处理的这个阶段,Page 对象会在每个控件上调用此方法。所有 ASP.NET Web 服务器控件都有一个用于写出发送给浏览器的控件标记的 Render 方法。  
  127.   
  128.     //如果创建自定义控件,通常要重写此方法以输出控件的标记。不过,如果自定义控件只合并标准的 ASP.NET Web 服务器控件,不合并自定义标记,则不需要重写 Render 方法。有关更多信息,请参见开发自定义 ASP.NET 服务器控件。  
  129.   
  130.     //用户控件(.ascx 文件)自动合并呈现,因此不需要在代码中显式呈现该控件。  
  131.  
  132.     #endregion  
  133.   
  134.     #region OnUnload 第十一步         
  135.     protected override void OnUnload(EventArgs e)  
  136.     {  
  137.         //该事件首先针对每个控件发生,继而针对该页发生。在控件中,使用该事件对特定控件执行最后清理,如关闭控件特定数据库连接。  
  138.   
  139.         //对于页自身,使用该事件来执行最后清理工作,如:关闭打开的文件和数据库连接,或完成日志记录或其他请求特定任务。  
  140.   
  141.         //注意    
  142.         //在卸载阶段,页及其控件已被呈现,因此无法对响应流做进一步更改。如果尝试调用方法(如 Response.Write 方法),则该页将引发异常。  
  143.    
  144.   
  145.         base.OnUnload(e);  
  146.     }  
  147.     #endregion  
  148. }  
当页面被提交请求第一个方法永远是构造函数。您可以在构造函数里面初始一些自定义属性或对象,不过这时候因为页面还没有被完全初始化所以多少会有些限制。
一、初始化

  ·当页面被提交请求第一个方法永远是构造函数。您可以在构造函数里面初始一些自定义属性或对象,不过这时候因为页面还没有被完全初始化所以多少会有些限制。特别地,您需要使用HttpContext对象。当前可以使用的对象包括QueryString, Form以及Cookies集合,还有Cache对象。注意:在构造函数里是不允许使用Session的。

  ·下一个将执行的方法是 AddParsedSubObject方法,这个方法将添加所有独立的控件并把页面组成一个控件集合树,这个方法经常被一些高级的页面模板解决方案 (Page Template Solutions)重写以便添加页面内容到页面模板(Page Template)中一些特殊的控件中。这个方法递归应用到所有的页面控件及相应的的每个子控件,所有的控件都是在这个方法中开始最早的初始化。

  ·页面类中下一个将执行的方法是DeterminePostBackMode。这个方法允许您修改IsPostBack的值及相关的事件。如果您需要从数据库中加载ViewState这个方法将特别有用,因为ViewState只有在IsPostBack为真的情况下才会进行恢复。返回空将会导致强制执行非回传,返回Request.Form则强制执行一个回传。除非在特殊情况下,否则并不建议去操作这个,因为这个还会影响其他的事件。

  ·下一个将要执行的方法是OnInit方法,一般这是第一个真正被使用的方法。这个方法触发时,所有页面定义中的控件执行初始化,这意味着所有在页面中定义的值应用到相应的控件上。不过,ViewState和传回的值还不会应用到控件上,因此,任何被代码或用户改变的值还没有被恢复到控件上。这个方法通常是最好的创建、重创建动态控件的好地方。

  二、恢复及加载

  ·下一个方法,LoadPageStateFromPersistenceMedium只会在页面被回传的时候才会被执行。如果因为使用Session或自定义存储方式,您修改了后面将要提到的影响ViewState保存方式的方法SavePageStateToPersistenceMedium,则这个方法需要被重写。默认的实现中ViewState是一种Base64格式编码,并且被保存在页面的隐藏域中,您可以使用这篇文章中提及的方法修改 ViewState按以上两种方式保存。注意:这个方法并没有真正加载ViewState到页面或页面控件中。

  ·当得到 ViewState后,下一个方法LoadViewSate,将以递归的方式恢复ViewState到页面及各个页面控件或子控件中。这个方法执行后,每个控件都将恢复到上一次的状态,但是用户提交的数据还没有应用到控件上,因为他们不是ViewState的一部分。这个方法主要用于恢复您在其他事件中动态生成的控件的值,他们的值是您手动保存在ViewSate中,并且现在已经失效。

  ·下一个方法是ProcessPostData,这个方法也同样是回传的时候才会被执行,并且不允许被重写,这个是页面基类的私有方法。这个方法通过匹配控件的名称恢复相应的用户提交的控件的值,到这一步意味着整个页面都已经被完全恢复了。唯一要记住的是所有动态控件的创建必须在这个方法之前。这个方法也是记录后面的改变事件的方法。

  ·下一个方法是OnLoad方法,通常这是用得最多的方法,因为这个方法是页面生存期第一个恢复了所有值的地方。大多数代码根据判断 IsPostBack来决定是否重新设置控件状态。您也可以在这个方法中调用Validate并且检查IsValid的值。也可以在这个方法中创建动态控件,并且该控件的所有的方法都会被执行以追上当前页面的状态包括ViewSate,不过不包括回传的值。

  三、事件处理

  ·下一个方法还是ProcessPostData,实际上就是前一个方法的另一次调用,它仍然是只在回传的时候执行并且由于是私有方法不可以被重写。如果您是第一次看页面的运行轨迹也许会觉得这个方法有些多余。但实际上这个方法是必要的因为在OnLoad中创建的动态控件也需要他们回传的值。任何在这以后创建的控件将可以得到他们的ViewState,但是不能再得到他们的回传的值,并且不会触发任何值改变事件(Change Event)。

  ·下一个方法,RaiseChangedEvents,也是只在回传页面中执行,并且也因为是基类的私有方法所有不能被继承。在整个页面生存期中,是在这儿根据之前的ProcessPostData记录的控件的值和提交的值是否不同来触发值改变事件。您也许需要调用Validate或者检查 IsValid的值。这里并没有特别的说明多个值改变事件的执行先后顺序。

  ·下一个方法,RaisePostBackEvent,同样是因为是基类的私有方法不能被继承,同样也是只在回传页面中执行。除非使用了AutoPostBack,不然这是实际提交表单事件执行的地方,特别是按钮或者其实使用javascript提交表单等。如果还没有被手动调用过并且使用了验证控件,那么Validate会被调用。注意IE中有个BUG有时会允许提交但却不触发任何事件。

·下一个方法是OnPreRender,一般这是在客户端展现页面之前改变页面及其控件的最后一次机会。您也可以在这个方法里面创建动态控件,并且所有的方法都会被执行以追上当前页面的状态包括ViewSate,但是私有方法将不会被执行,这意味着不会有回传的值并且不会有事件触发。由于IE中的BUG,这是一个没有事件赶上PostBack的好地方。

  四、保存及显示

   ·下一个方法是SaveViewState,不论是否是回传页面,均会递归的执行以保存页面及其所有控件的ViewState。ViewState基本上保存所有与定义在aspx中的原始值不同的值,不管是被代码还是用户所改变。注意控件值是根据他们在页面的控件树中的位置来保存的,所以如果动态控件后来加到了错误的位置将会导致混乱。

  ·下一个方法是SavePageStateToPersistenceMedium真正的保存页面的 ViewSate。这个方法随同LoadPageStateFromPersistenceMediumg 一起被重写以便保存ViewState到Session或其它自定义数据,而不是用隐藏域。这对于低带宽的用户来说是很有帮助的。并且对于移动设备来说,Session是默认设置。下面这篇文章描述了使用以上两种方式保存ViewState的具体细节。注意在Asp.net中有个 Bug:Asp.net要求必须提交__viewstate字段,即使是空的。

  ·下一个方法是Render方法,该方法递归的创建并发送相应控件的html给浏览器。这个方法被一些页面模板方案重写以添加一些通用的页面头与脚而不使用服务器控件,他们总是有一些额外的东西。注意这儿的修改只能使用纯HTML,因为控件在这儿已经被生成了。您可以用StringBuilder,StringWriter,HtmlTextWriter捕获相应的HTML输出。

  · 最后的方法是OnUnload,这个方法会调用相应的Dispose方法。这个方法提供机会以便清空该页面中使用的非托管资源,如关闭打开的文件句柄,以前打开的数据库连接等。注意这个方法是在页面已经发送到客户端以后执行的,所以它只有影响服务器对象,并且它不会显示在页面的显示轨迹中。这就是页面的生存期,对于每一次请求都是这么运行的。

  表1:页面事件总结

  方法回传控件

C#代码 
  1. ConstructorAlwaysAll  
  2.   
  3. AddParsedSubObjectAlwaysAll  
  4.   
  5. DeterminePostBackModeAlwaysPage  
  6.   
  7. OnInitAlwaysAll  
  8.   
  9. LoadPageStateFromPersistenceMediumPostBackPage  
  10.   
  11. LoadViewStatePostBackAll  
  12.   
  13. ProcessPostData1PostBackPage  
  14.   
  15. OnLoadAlwaysAll  
  16.   
  17. ProcessPostData2PostBackPage  
  18.   
  19. RaiseChangedEventsPostBackPage  
  20.   
  21. RaisePostBackEventPostBackPage  
  22.   
  23. OnPreRenderAlwaysAll  
  24.   
  25. SaveViewStateAlwaysAll  
  26.   
  27. SavePageStateToPersistenceMediumAlwaysPage  
  28.   
  29. RenderAlwaysAll  
  30.   
  31. OnUnloadAlwaysAll  

msdn上的说明:(http://msdn.microsoft.com/zh-cn/library/ms178472(VS.80).aspx)

一般来说,页要经历下表概述的各个阶段。除了页生命周期阶段以外,在请求前后还存在应用程序阶段,但是这些阶段并不特定于页。有关更多信息,请参见 ASP.NET 应用程序生命周期概述。

阶段说明

页请求

页请求发生在页生命周期开始之前。用户请求页时,ASP.NET 将确定是否需要分析和编译页(从而开始页的生命周期),或者是否可以在不运行页的情况下发送页的缓存版本以进行响应。

开始

在开始阶段,将设置页属性,如 Request 和 Response。在此阶段,页还将确定请求是回发请求还是新请求,并设置IsPostBack 属性。此外,在开始阶段期间,还将设置页的 UICulture 属性。

页初始化

页初始化期间,可以使用页中的控件,并将设置每个控件的 UniqueID 属性。此外,任何主题都将应用于页。如果当前请求是回发请求,则回发数据尚未加载,并且控件属性值尚未还原为视图状态中的值。

加载

加载期间,如果当前请求是回发请求,则将使用从视图状态和控件状态恢复的信息加载控件属性。

验证

在验证期间,将调用所有验证程序控件的 Validate 方法,此方法将设置各个验证程序控件和页的 IsValid 属性。

回发事件处理

如果请求是回发请求,则将调用所有事件处理程序。

呈现

在呈现之前,会针对该页和所有控件保存视图状态。在呈现阶段中,页会针对每个控件调用 Render 方法,它会提供一个文本编写器,用于将控件的输出写入页的 Response 属性的 OutputStream 中。

卸载

完全呈现页并已将页发送至客户端、准备丢弃该页后,将调用卸载。此时,将卸载页属性(如 Response 和Request)并执行清理。

asp.net页面事件执行顺序