Asp.Net的Life Cycle原来如此重要
Again, Why?
我们来看一个有趣的例子。假定我们想实现一个简单的不能再简单的功能:一个数字是0,我想要点击一个按钮让它变成5。在asp.net中,你会怎么写?例如:
Notice: 本例子目的是用于演示Life Cycle的过程,对于这么简单的问题可以参考留言中7楼和10楼的方法,但是希望战友们可以由此看到更多的东西。另外由于这是俺第一次写文章,例子也是临时编造的一个,因此可能欠妥,请多多包涵了。:)
// Default.aspx.cs
public partial class _Default : System.Web.UI.Page
{
int x = 0;
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = x.ToString();
}
protected void btnChangeMe_Click(object sender, EventArgs e)
{
x = 5;
}
}
<!-- Default.aspx -->
<p>
<asp:Button runat="server" Text="Change" ID="btnChangeMe"
onclick="btnChangeMe_Click" />
</p>
<p>
<asp:Label ID="Label1" runat="server" Text="0"></asp:Label>
</p>
然后编译运行,请问结果是如何呢?
让我们来看看逻辑。我们点击按钮,触发事件,然后x变成了5,然后页面上的x.ToString()也应该是5。可是残酷的现实告诉你,非也,只会一直显示0,0,0,0 for good。
可能聪明的战友们已经猜到了,是不是在对x赋值前,Label1的属性值就已经设置完毕了呢?也就是说,如果Label1.Text = x.ToString()语句在x=5之前就执行结束了,那么结果仿佛就理所当然了。
正确。这也就是说,如果没有掌握正确的代码执行流程,你逻辑上以为理所当然的东西,就会成为一个陷阱。*@#(*¥&(……
让我们来看看为什么会有这样的执行顺序,请参考本文最后的列表,注意红字的部分。可以清楚地看到,Control Events是在Load事件结束后才执行的。也就是说,我们的Page_Load函数先执行,然后才会去调用btnChangeMe_Click。
Solution 1 : Change Value Before Load Event
添加如下代码:
protected override void OnPreLoad(EventArgs e)
{
base.OnPreLoad(e);
x = 5;
}
Solution 2 : Set Value After Control Event
把方案1换成如下代码:
protected override void OnPreRender(EventArgs e)
{
Label1.Text = x.ToString();
base.OnPreRender(e);
}
可以看到,正如我们想要的那样,初始化的时候是0,点击以后就变成5了。 :)
Some Key Events
这其中最常用到得几个时间简单介绍如下:
PreInit
这个事件用来动态生成控件,设置master page以及theme,同时在这里可以操控profile的值了。
Init
这个事件可以用来读取或者初始化控件属性。注意:这里只是初始化的属性,包含的仅仅是外观等属性,而其Value在这里尚未载入。
PreLoad
在这里,所有控件的Value已经加载,因此可以对其进行读取操作了。
Load
用这个事件来对控件进行属性设置,同时如果需要的话可以在这里打开数据库连接。
Control Event
就是你的各个控件触发的事件在这里才会执行。
PreRender
这里可以对控件以及所有内容做最后的修改。
Render
实际上这不是一个事件。但是这里可以对最后生成的Html代码进行最后的加工。
Conclusion
这里对life cycle的主要事件做了一些简单介绍,实际上还有更多复杂的情形,例如数据控件中间的事件,数据绑定时的事件等等,留着下回再说吧。这个列表是微软官方推荐的Typical Use,但是实际上可以根据实际情况做很多灵活变动——当然,灵活也就意味着可能引起混乱,本人的血的教训……
Appendix
Page Event |
Typical Use |
---|---|
Use this event for the following:
|
|
Raised after all controls have been initialized and any skin settings have been applied. Use this event to read or initialize control properties. |
|
Raised by the Page object. Use this event for processing tasks that require all initialization be complete. |
|
Use this event if you need to perform processing on your page or control before the Load event. Before the Page instance raises this event, it loads view state for itself and all controls, and then processes any postback data included with the Request instance. |
|
The Page calls the OnLoad event method on the Page, then recursively does the same for each child control, which does the same for each of its child controls until the page and all controls are loaded. Use the OnLoad event method to set properties in controls and establish database connections. |
|
Control events |
Use these events to handle specific control events, such as a Button control's Click event or a TextBox control's TextChanged event. |
Use this event for tasks that require that all other controls on the page be loaded. |
|
Before this event occurs:
The PreRender event occurs for each control on the page. Use the event to make final changes to the contents of the page or its controls. |
|
Before this event occurs, ViewState has been saved for the page and for all controls. Any changes to the page or controls at this point will be ignored. Use this event perform tasks that require view state to be saved, but that do not make any changes to controls. |
|
This is not an event; instead, at this stage of processing, the Page object calls this method on each control. All ASP.NET Web server controls have a Render method that writes out the control's markup that is sent to the browser. If you create a custom control, you typically override this method to output the control's markup. However, if your custom control incorporates only standard ASP.NET Web server controls and no custom markup, you do not need to override the Render method. For more information, see Developing Custom ASP.NET Server Controls. A user control (an .ascx file) automatically incorporates rendering, so you do not need to explicitly render the control in code. |
|
This event occurs for each control and then for the page. In controls, use this event to do final cleanup for specific controls, such as closing control-specific database connections. For the page itself, use this event to do final cleanup work, such as closing open files and database connections, or finishing up logging or other request-specific tasks. Note:
During the unload stage, the page and its controls have been rendered, so you cannot make further changes to the response stream. If you attempt to call a method such as the Response.Write method, the page will throw an exception.
|