大家最常见的Page事件的应用莫过于Page_Load方法,当我们新建一个webform页面,cs页里面会默认包含一个Page_Load方法。本人比较惭愧的是,除此之外的其他Page事件基本没有使用过,也不知道该如何使用。
最近在PetShop for .NET3.5上注意到一些有关的细节,在这里想跟大家讨论一下,希望大家能够补充指正。
其中购物车页面(ShoppingCart.aspx)的cs页源码如下:
2
3 public partial class ShoppingCart : System.Web.UI.Page {
4
5 protected void Page_PreInit( object sender, EventArgs e) {
6 if ( ! IsPostBack) {
7 string itemId = Request.QueryString[ " addItem " ];
8 if ( ! string .IsNullOrEmpty(itemId)) {
9 Profile.ShoppingCart.Add(itemId);
10 Profile.Save();
11 // Redirect to prevent duplictations in the cart if user hits "Refresh"
12 Response.Redirect( " ~/ShoppingCart.aspx " , true );
13 }
14 }
15 }
16 }
大家注意到这里用的是Page_PreInit方法,大致内容是获取前一页传来的查询字符串(商品标识),将其存入购物车(数据库),然后重新定位到本页,并终止了本页的继续执行。该方法没有对DOM进行任何操作,只有简单的入库,所以,此操作放入Page_PreInit方法内是最好不过的,因为Page_PreInit方法是Page首先执行的事件,重定向(Redirect)后剩余的事件都不会执行,效率理应是最高的。
相对应的我们再来看一下Page_PreRender方法,这个例子来源于本页的一个用户控件的代码页(ShoppingCartControl.ascx.cs),如下:
2 /// Handle Page load event
3 /// </summary>
4 protected void Page_PreRender( object sender, EventArgs e) {
5 if ( ! IsPostBack) {
6 BindCart();
7 }
8 }
9
10 /// <summary>
11 /// Bind repeater to Cart object in Profile
12 /// </summary>
13 private void BindCart() {
14
15 ICollection < CartItemInfo > cart = Profile.ShoppingCart.CartItems;
16 if (cart.Count > 0 ) {
17 repShoppingCart.DataSource = cart;
18 repShoppingCart.DataBind();
19 PrintTotal();
20 plhTotal.Visible = true ;
21 }
22 else {
23 repShoppingCart.Visible = false ;
24 plhTotal.Visible = false ;
25 lblMsg.Text = " Your cart is empty. " ;
26 }
27
28 }
很明显这是绑定用户控件内容的方法,那为什么要放在Page_PreRender方法下呢?放到Page_Load方法下不行吗?答案当然是可以的。只不过在这里Page_PreRender方法更合适。要知道Page_PreRender是在Page_Load之后才发生的。MSDN关于此方法的解释是:“在加载 Control 对象之后、呈现之前发生。使用该事件在服务器控件呈现给页之前执行任何更新。”可以理解成在所有的代码执行完毕,呈现DOM之前发生的事件。所以,这个例子放到Page_PreRender事件中试最保险和最合理的方式。毕竟,我们可以把一些其他的方法放到之前的事件中执行,比如Page_Load。
ASP.NET WebForm区别于ASP.NET MVC 很大的不同就在于事件驱动上。今天讲的这两个例子Page_PreInit和Page_PreRender一个在最前面执行,一个在相对靠后的地方执行。它们各司其职,让WebForm尽展其魅力。当然,假如我们使用不当,WebForm更是让MVC所不齿。所以,我们要做的就是看清楚事务本质,合理使用,这样的编程才有意义。