ASP.net 事件触发顺序

PreInit

OnInit

LoadViewState

LoadPostBackData

Page_Load

Control Event Handlers

PreRender

SaveViewState

Render

Unload

 

了解页的生存周期中的每一个请求是非常重要的,丢值丢状态的问题都可能是你对页的生存周期了解不够造成的当然,如果你要在asp保留状态的话,可以用诸如Application,Session,Cache,或者Cookies之类的

注意:asp 2.0中的视图状态由两部分组成,控件状态和视图状态详细了解请参考这篇文章 http://msdn2.microsoft.com/en-us/library/1whwt1k7(VS.80).aspx

除了Init()和Unload()之外的所有事件都是从最外面到最里面被激发的

1. PreInit()    在这个页面级的事件中,所有在设计时创建的控件都将被用默认值做初始化例如,如果你有一个Text属性值为Hello的TextBox控件,则此时这个属 性被设置我们也可以在这里动态的创建控件

这个事件仅仅发生在页级别的类中,用户控件和母版页没有这个事件

下面的代码示例了如何重写这个方法以增加你的自定义代码

protected override void OnPreInit(EventArgs e)

{ // custom code base.OnPreInit(e); } 注意,我们只能在PreInit()事件中动态的设置themes

使用母版页时的特例 我们先要了解一个非常重要的知识点母版页被处理的过程就相当于内容页中的一个控件

所以如果一个页有其相关联的母版页的话,那么在PreInit()事件里页中的所有控件都不会被初始化而只有在Init()事件开始之后,你才能直接访问这些控件为什么?

这个原因就是内容页中的所有控件都包含在ContentPlaceholder里,而ContentPlaceholder其实就是母版页的一个子 控件现在母版页被处理的过程就相当于内容页中的一个控件,我们早先提到过,除了Init()和Unload()之外的所有事件都是从最外面到最里面被激发 的虽然页的PreInit()是第一个被触发的事件,但是用户控件和母版页是没有这个事件的,所以在页的Page_PreInit()方法中,母版页和用 户控件都不会被初始化,而是在Init()事件之后

接下来让我们来看一下Page_Init()事件之后控件的层次结构

2. OnInit() 在这个事件里,我们能读出控件的属性(在设计模式中设置的)但是我们不能读出用户设置的值,因为得到用户设置的值是在LoadPostData()事件被 激发之后不过在这个事件中我们可以得到POST数据,如下 string selectedValue = Request.Form[controlID].ToString();

3. LoadViewState 这个事件仅仅在回发之后被激发(IsPostBack == true)在这个事件中runtime从隐藏域中分解出view state并加载到所有启用了view state的控件

4. LoadPostBackData 这个事件也仅仅是在回发之后被激发 在这个事件里实现了IPostBackDataHandler接口的控件从HTTP的POST数据中得到值注意,textbox控件不能从view state中获得值,而是在此事件中从POST数据中获得值所以即使有些控件没有启用view state,只要它实现了IPostBackDataHandler接口就可以从HTTP的POST数据中得到值

另一个重要的知识点是如果我们有一个DropDownList控件并动态的给它增加一些选择项,那么runtime将不能得到这些值除非启用了 view state(即使控件继承自IPostBackDataHandler接口)这个原因就是在HTTP的POST数据中的每一个控件只能有一个值,并且 POST数据中的所有值都不会被保存,除了使用view state

5. Page_Load 这是最常用的方法了,而且是一些开发新手放置他们代码的第一个地方,有些新手们往往认为这就是Page类第一个触发的方法这个方法是混淆我们Page生存周期的罪魁祸首之一

注意:如果页里有任何用户控件的话,那么用户控件的Load方法将在页类的Load方法之后被触发这个原因早先已经解释过了,除了Init()和 Unload()之外的所有事件都是从最外面到最里面被激发的所以页的Page_Load()之后,页内的其它控件的Load方法才被触发

6. Control Event Handlers 事件处理(比如像Button1_Click()之类的)是定义在ASPX页面中的,有一些开发人员认为当单击一个按钮后会立即出发 Button_Click() ,他们忘了在这个事件触发之前首先要触发Page_Load

7. PreRender 如果我们想改变某一个控件的值,这是最后的机会了

8. SaveViewState 控件的ViewState被存储在form的隐藏域中

9. Render 呈现

10. Unload 这是最后的清理操作 --------------------------------- 动态控件 现在我们已经知道了页的生存周期的重要事件,接下来让我们关注一下如何创建以及保持动态生成控件的状态有的时候我们需要动态的生成控件,比如我原来管理的 一个酒店预订的项目,用户在一个TextBox里输入房间号,根据这个值动态的生成一个用户控件来显示该房间的详细信息

开发人员虽然能动态的生成用户控件,但是却不能保存用户控件的状态当我看了代码后,他们把生成控件的代码写到了Button的Click事件里根据 我们上面所讨论的,Button_Click()在LoadViewState()和LoadPostData()之后触发,而控件的值是要在view state或POST数据中取得的

所以除非在Page_Init()或Pre_Init()方法里重新创建控件(它们发生在LoadViewState和LoadPostData之前),这样就可以在下一个事件里获得控件的值

现在,如果把代码写到Page_Init()事件里的话,将不能得到用户在TextBox(它是一个静态控件)里输入的值原因就在于这是Page_Init()事件,控件的值被初始化为它们设计时的默认值,而不会得到用户输入的值

所以如果要在这里访问到用户输入的值话只有一个办法,就是从POST数据中取值代码如下

protected override void OnInit(EventArgs e)

{ // 通过Post数据得到用户在TextBox里输入的值

string selectedValue ;

if(Request.Form["txtNoOfRooms"] != null)

selectedValue = Request.Form["txtNoOfRooms"].ToString();

// 动态生成控件的代码

 

base.OnInit(e); }

注意:感谢ASP.NET论坛的Mike Banavige,有了他的帮助才让我增加了这部分内容如果你在Page_Load事件里创建一个动态控件,并把它添加到PlaceHolder或 Panel里(要打开view state),那么动态控件将会维持它的状态,即使它不是在Page_Init()中创建的,为什么?动态控件 现在我们已经知道了页的生存周期的重要事件,接下来让我们关注一下如何创建以及保持动态生成控件的状态有的时候我们需要动态的生成控件,比如我原来管理的 一个酒店预订的项目,用户在一个TextBox里输入房间号,根据这个值动态的生成一个用户控件来显示该房间的详细信息

开发人员虽然能动态的生成用户控件,但是却不能保存用户控件的状态当我看了代码后,他们把生成控件的代码写到了Button的Click事件里根据 我们上面所讨论的,Button_Click()在LoadViewState()和LoadPostData()之后触发,而控件的值是要在view state或POST数据中取得的

所以除非在Page_Init()或Pre_Init()方法里重新创建控件(它们发生在LoadViewState和LoadPostData之前),这样就可以在下一个事件里获得控件的值

现在,如果把代码写到Page_Init()事件里的话,将不能得到用户在TextBox(它是一个静态控件)里输入的值原因就在于这是Page_Init()事件,控件的值被初始化为它们设计时的默认值,而不会得到用户输入的值

所以如果要在这里访问到用户输入的值话只有一个办法,就是从POST数据中取值代码如下 protected override void OnInit(EventArgs e) { // 通过Post数据得到用户在TextBox里输入的值 string selectedValue ; if(Request.Form["txtNoOfRooms"] != null) selectedValue = Request.Form["txtNoOfRooms"].ToString();

// 动态生成控件的代码

 

base.OnInit(e); } 注意:感谢ASP.NET论坛的Mike Banavige,有了他的帮助才让我增加了这部分内容如果你在Page_Load事件里创建一个动态控件,并把它添加到PlaceHolder或 Panel里(要打开view state),那么动态控件将会维持它的状态,即使它不是在Page_Init()中创建的,为什么?原因就是控件一旦被添加到页的控件树 里,TrackViewState()方法就负责跟踪其状态只要控件被添加到控件树里,这个方法就会被自动的触发因为这个原因,对控件的任何修改(如添加 item之类的)都应该在动态控件被添加到页的控件树之后来做,否则其状态将丢失请看如下代码 protected void Page_Load(object sender, EventArgs e) { // 创建一个DropDownList DropDownList d = new DropDownList();

// TrackViewState()方法将被触发去跟踪这个DropDownList的状态,所以其状态将被保持 PlaceHolder1.Controls.Add(d);

if (!IsPostBack) { d.Items.Add("test1"); d.Items.Add("test2"); } }

下面的代码则不会保持动态控件的状态 protected void Page_Load(object sender, EventArgs e) { // 动态创建一个控件 dropdownDropDownList d = new DropDownList(); if (!IsPostBack) { d.Items.Add("test1"); d.Items.Add("test2"); }

// "test1"和"test2"值将丢失 PlaceHolder1.Controls.Add(d); }

总结 我已经解释了页的生存周期的一些相关事件及其重要性,同时我也会不定期更新这篇文章以增加一些小提示和小技巧,此外也欢迎读者指出本文的缺陷之处及修改建 议 记住页的整个生存周期的各个事件的顺序是非常重要的,这样我们就可以根据不同的需求在合适的位置写出相应的代码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值