ASP.NET的事件模型(很适合学习的文章)
在default.aspx的页面中第一行是一条页面指令:
<%@ page language="c#" autoeventwireup="true" codebehind="default.aspx.cs" inherits="aspxeventsmodel._default" %>
其中codebehind属性指定代码隐藏页面的名称,inherits指定所属的命名空间和类,autoeventwireup属性是可以赋值为true和false,默认是赋值为true。
我们先在default.aspx页面中放入两个literal控件:
<asp:literal id="liinit" runat="server"></asp:literal>
<br />
<asp:literal id="liload" runat="server"></asp:literal>
在default.aspx.cs页面中,默认会存在page_load方法,定义如下:
protected void page_load(object sender, eventargs e)
{
this.liload.text = "这是在页面load事件";
}
页面被请求,在页面加载的时候会执行该方法。
那么这个方法为什么会在页面加载的时候执行,这个方法我们并没有给它注册给页面相应的事件。
页面的事件也有很多,我们列出一些重要页面的事件看一下:
在page类中存在下面的事件,page类是页面的基类:
public event eventhandler initcomplete;
public event eventhandler loadcomplete;
public event eventhandler preinit;
public event eventhandler preload;
public event eventhandler prerendercomplete;
public event eventhandler savestatecomplete;
在control类中存在下面的事件,control类是page类的基类:
public event eventhandler databinding;
public event eventhandler disposed;
public event eventhandler init;
public event eventhandler load;
public event eventhandler prerender;
我们对这其中比较关注的事件提取出来,并根据事件的执行顺序来排序:
preinit:在页面的初始化阶段开始时引发
init:在页面的初始化时引发
initcomplete:在页面的初始化结束时引发
preload:在页面的加载阶段开始时引发
load:在页面的加载时引发
loadcomplete:在页面的加载结束时引发
prerender:在页面即将被呈现时引发
我们看到页面事件有很多,主要来研究init和load这两个事件。在default.aspx.cs页面中,添加page_init方法,定义如下:
protected void page_init(object sender, eventargs e)
{
this.liinit.text = "这是在页面init事件";
}
那么还是回到上面的问题,为什么会在页面请求之后执行page_init、page_load方法?原因是:
asp.net中autoeventwireup="true",使页面与某些特殊的事件方法绑定,自动识别这些具有特定名称的方法,而不需要进行注册事件。
这些特定名称包括:page_init, page_load等。这里就说明:init事件会自动与page_init方法绑定,load事件自动与page_load方法绑定。当然这些都是autoeventwireup="true"的功劳,当我们autoeventwireup="false"的时候,再次请求页面的时候,page_init、page_load方法是不会被执行的。那么我们可以显示注册事件:
protected override void oninit(eventargs e)
{
this.init += new eventhandler(this.page_init);
base.oninit(e);
}
protected override void onload(eventargs e)
{
this.load += new eventhandler(this.page_load);
base.onload(e);
}
那么oninit和onload又是什么来头呢?
它们是control类中定义的虚方法,所以我们可以在它的子类里面进行重写。
看asp.net 的注释是这样描写的:
oninit:引发 system.web.ui.control.init 的事件。
onload:引发 system.web.ui.control.load 的事件。
很好啊,我们在这边对它们重写,并注册事件合情合理。
我们把对init注册事件语句放到onload方法中,把对load注册事件语句放到oninit方法中,是两个处理的内容交换一下看看会有什么结果:
protected override void oninit(eventargs e)
{
this.load += new eventhandler(this.page_load);
base.oninit(e);
}
protected override void onload(eventargs e)
{
this.init += new eventhandler(this.page_init);
base.onload(e);
}
我们请求页面发现:在oninit方法中对load注册事件执行了,在onload方法中对init注册事件并没有执行。原因是在执行oninit方法之后,就表示init事件已经响应完成,在之后再对init事件注册方法,并不会得到调用。而在oninit方法中对load注册事件的时候,load事件并没有开始触发,这个时候对load注册事件是有效的。所以现在我们很多时候,都形成了一种规范,只会重写oninit方法,不重写onload方法,也能完成我们的需求。所以在有些框架里面看不到onload方法就是这样形成的。我们把default.aspx.cs页面调整成:
protected override void oninit(eventargs e)
{
this.init += new eventhandler(this.page_init);
this.load += new eventhandler(this.page_load);
base.oninit(e);
}
很明显我们觉得不需要page_init和page_load方法,我们再次调整为:
protected override void oninit(eventargs e)
{
this.liinit.text = "这是在页面init事件";
this.liload.text = "这是在页面load事件";
base.oninit(e);
}
我附上调试的源码default.aspx:
<%@ page language="c#" autoeventwireup="false" codebehind="default.aspx.cs" inherits="aspxeventsmodel._default" %>
<!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<asp:literal id="liinit" runat="server"></asp:literal>
<br />
<asp:literal id="liload" runat="server"></asp:literal>
</body>
</html>
default.aspx.cs:
using system;
using system.collections.generic;
using system.linq;
using system.web;
using system.web.ui;
using system.web.ui.webcontrols;
namespace aspxeventsmodel
{
public partial class _default : system.web.ui.page
{
protected override void oninit(eventargs e)
{
this.liinit.text = "这是在页面init事件";
this.liload.text = "这是在页面load事件";
//this.init += new eventhandler(this.page_init);
//this.load += new eventhandler(this.page_load);
base.oninit(e);
}
//protected override void onload(eventargs e)
//{
// this.load += new eventhandler(this.page_load);
// //this.init += new eventhandler(this.page_init);
// base.onload(e);
//}
//protected void page_init(object sender, eventargs e)
//{
// this.liinit.text = "这是在页面init事件";
//}
//protected void page_load(object sender, eventargs e)
//{
// this.liload.text = "这是在页面load事件";
//}
}
}
好了,赶快自己动手试试吧。