ASP.NET页面——页面事件
上篇文章写到ASP.NET页面的生命周期。详见:http://www.cnblogs.com/zhaozhan/archive/2009/06/21/1507740.html。
Page_PreInit事件来执行以下操作:检查IsPostBack属性来确定是不是第一次处理该页,创建或重新创建动态控件,动态设置主控页,动态设置Theme属性,读取或设置配置文件的属性值。如果请求回发请求,则空间的值尚未从视图状态还原,如果在此阶段设置控件属性,则其值可能在下一时间中被重写。
Page_Init事件中所有的控件都设为默认的状态,但此时视图状态没有被恢复。这意味着Page_Init不应该用来处理服务器控件的值和状态。
InitComplete事件由Page对象引发。使用该事件来处理要求先完成所有初始化工作的任务。
Page_PreLoad:如果需要在Load事件之前对页或控件执行处理使用。在Page引发该事件后,它会为自身和所有控件加载视图状态,然后会处理Request实例包括的任何回发数据。
Page_Load事件是ASP.NET编程中最常用的时间。它在Page_Init事件之后调用。Page_Load事件和Page_Init事件之间的主要差别是到触发Page_Load事件时。所有的服务器空间的视图状态都将被恢复。这使得该时间可以很理想地用于操纵空间并准备页面的内容,然后再呈现给客户端。
控件事件在页面初始化阶段之后进行处理。来处理特定控件的事件,如Button控件的Click事件或TextBox控件的TextChanged事件。在回发请求中,如果页包含验证程序控件,请在执行任何处理之前Page和各个验证控件的IsValid属性。
LoadComplete事件来处理加载页面上的所有其他控件的任务。
PreRender事件对页或其空间的内容进行最后的更改。
SaveStateComplete:在该事件发生前,已针对页和所有控件保存了ViewState。将忽略此时对页或控件进行的任何更改。
使用该事件执行满足以下条件的任务:要求已经保存了视图状态,但未对控件进行任何更改。
Render:这不是事件;在处理的这个阶段,Page对象会在每个控件上调用此方法。所有 ASP.NET Web 服务器控件都有一个用于写出发送给浏览器的控件标记的Render方法。如果创建自定义控件,通常要重写此方法以输出控件的标记。不过,如果自定义控件只合并标准的 ASP.NET Web 服务器控件,不合并自定义标记,则不需要重写Render方法。用户控件(.ascx 文件)自动合并呈现,因此不需要在代码中显式呈现该控件。
UnLoad事件首先针对每个控件发生,继而针对该页发生。在控件中,使用该事件对特定控件执行最后清理,如关闭控件特定数据库连接。
对于页自身,使用该事件来执行最后清理工作,如:关闭打开的文件和数据库连接,或完成日志记录或其他请求特定任务。在卸载阶段,页及其控件已被呈现,因此无法对响应流做进一步更改。如果尝试调用方法(如Response.Write 方法),则该页将引发异常。
下面做个简单的Demo:
在下面的例子,创建一个投票的Web窗体,允许用户投票选择喜爱的颜色。
<form id="form1" runat="server"> <div style=" color:Maroon; font-size:5; font-weight:bold;"> <h2>Vote For Your Favorite Color!</h2> <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" BorderColor="#DEDA84" BorderStyle="None" CellPadding="3" CellSpacing="2" BorderWidth="1px" BackColor="#DEBA84"> <SelectedRowStyle Font-Bold="true" ForeColor="White" BackColor="#738A9C" /> <RowStyle ForeColor="#8C4510" BorderColor="#FFF7E7" /> <HeaderStyle Font-Bold="true" ForeColor="White" BackColor="#A55129"/> <FooterStyle ForeColor="#8C4510" BackColor="#F7DFB5" /> <Columns> <asp:BoundField DataField="Key" HeaderText="Name" /> <asp:BoundField DataField="Value" HeaderText="# of Votes" /> <asp:ButtonField Text="Vote" ButtonType="Button" HeaderText="Vote" CommandName="Vote" /> </Columns> </asp:GridView> </div> <asp:Button ID="btnReset" runat="server" Text="Reset Votes" /> </form>
在Page_Load事件中:或者把所有的投票数设为初始的零值,或者从应用程序的缓存中检索投票数。
protected Hashtable VoteTally; protected string[] ColorList = { "Red","Green","Blue","Black","White"}; protected void Page_Load(object sender, EventArgs e) { VoteTally = new Hashtable(); foreach (string strKey in ColorList) { if (Cache.Get(strKey) == null) VoteTally.Add(strKey, 0); else VoteTally.Add(strKey, Cache.Get(strKey)); } }
在页面卸载时,把这些值缓存起来,是页面的所有其他用户也能投票。
protected void Page_UnLoad(object sender, EventArgs e) { foreach (string strKey in ColorList) { Cache.Insert(strKey, VoteTally[strKey]); } }
当用户点击某一行的命令按钮投票选择一种颜色时,触发RowComand。这是一个事件起泡(event bubbling),容器控件中的一个子控件引起容器控件的一个事件被触发。控件事件是在Page_Load事件触发之后触发的。
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e) { if (e.CommandName == "Vote") { int id = Convert.ToInt32(e.CommandArgument); string strKey = GridView1.Rows[id].Cells[0].Text.ToString(); VoteTally[strKey] =(int) VoteTally[strKey] + 1; } }
在Page_PreRender事件期间把数据源绑定到GridView。在PreRender事件绑定的好处是可以清除两次绑定数据的情况(一次在Page_Load中,一次在RowComand中),通过把绑定放到Page_PreRender中,只需把绑定数据的代码放到一个地方,它可以覆盖所有的情况。
private void Page_PreRender(object sender, EventArgs e) { GridView1.DataSource = VoteTally; GridView1.DataBind(); }
清除所有的缓存。重新投票计数。
protected void btnReset_Click(object sender, EventArgs e) { foreach (string strKey in ColorList) { VoteTally[strKey] = 0; Cache.Insert(strKey, 0); } }
页面的显示效果如下:
在Global.asax设置Application_BeginRequest和Application_EndRequest方法。统计页面时间。
void Application_BeginRequest(object sender, EventArgs e) { Application[Request.UserHostAddress.ToString()] = DateTime.Now; } void Application_EndRequest(object sender, EventArgs e) { DateTime sTime = (DateTime)Application[Request.UserHostAddress.ToString()]; Application.Remove(Request.UserHostAddress.ToString()); Response.Write("<hr/>"); Response.Write("Total Page Processing Time="); Response.Write((DateTime.Now.Ticks-sTime.Ticks)/1000000.0); Response.Write("Seconds"); }