技术开发 频道

关于ASP.NET页面生命周期的整体把握

  上面最主要的3点:

  (1)javascript:__doPostBack()和Request.Form["__EVENTARGUMENT"];__doPostBack()第一个参数必须用控件的name 而不是ID。控件名为将父控件ID用$符号连接起来的。第二个参数是传给控件的Value值。第一个参数对应 Request.Form["__EVENTTARGET"]; 第二个参数对应Request.Form["__EVENTARGUMENT"]。此函数是DOTNET 的服务器控件产生的,所以要使用此函数,必须整个页面上至少要有一个控件可以回传页面。其实,dotnet 服务器控件在页面上产生两个隐藏的控件一个名为__EVENTTARGET ,另一个名为__EVENTARGUMENT。

  (2)ViewState视图状态保存的是页面级别的内容。CurrentID = Request.Form["__EVENTARGUMENT"];

  (3)点击后将导致事件的触发(回传)。 Changed();

  (三)页面的事件与委托处理

public partial class Default : Core.UserParentPage
     {
         protected void Page_Init(
object sender, EventArgs e)
         {
             Core.Trace.TraceInfo(
"Default  OnInit");
        }

         protected void Page_Load(
object sender, EventArgs e)
         {
             Core.Trace.TraceInfo(
"Default   Page_Load");
             userEventControl.Changed
+=new UserControl.UserEventControl.ChangedHandler(userEventControl_Changed);
         }

        
private void userEventControl_Changed()
         {
             Core.Trace.TraceInfo(
"Default   userEventControl_Changed");
            
            
string id = userEventControl.CurrentID;
             ViewState[
"ID"] =id;//保存状态进行相应的处理
            lblShow.Text
=id;
         }
     }


 

  这一步最关键,利用userEventControl.Changed+=new UserControl.UserEventControl.ChangedHandler(userEventControl_Changed),当事件触发时,我们能够通过userEventControl_Changed()方法获取点击的value值,用视图状态保存该值,进而进行相应的操作(控制)。页面显示如下:

1
 

  (四)跟踪文件为当前目录下的trace.txt文件

public static class Trace
    {
        
private static string logPath = HttpContext.Current.Request.PhysicalApplicationPath;
        
public static void TraceInfo(string information)
         {
            
string path = logPath + @"trace.txt";
            
string sqltemp = DateTime.Now.ToString("yyy-MM-dd hh:mm:ss fff") + ": " + information;
             FileStream fs
= null;
            
if (!File.Exists(path))
             {
                 fs
= File.Create(path);
                 fs.Close();
             }
             StreamWriter sw
= new StreamWriter(path, true, Encoding.UTF8);
             sw.WriteLine(sqltemp);
             sw.Close();
         }
    }

 

  在每个页面上的事件中增加自定义跟踪,可以发现如下情况:Init和Load都在每个控件上递归方式发生,但它们发生的顺序是相反的。每个子控件的Init与Unload事件在其容器引发相应的事件之前发生。容器的Load事件是在其子控件的Load事件之前发生。

  trace.txt内容显示如下(生成页面的过程以及点击事件触发跟踪):

2010-11-23 02:26:29 828: UserEventControl  OnInit
2010-11-23 02:26:29 828: UserParentPage  OnInit
2010-11-23 02:26:29 828: Default  OnInit
2010-11-23 02:26:29 828: UserParentPage  OnLoad
2010-11-23 02:26:29 828: Default   Page_Load
2010-11-23 02:26:29 828: UserEventControl  OnLoad
2010-11-23 02:26:29 828: UserEventControl  OnLoad  !Page.IsPostBack==true
2010-11-23 02:26:29 828: UserEventControl  OnLoad
2010-11-23 02:26:29 828: UserEventControl  OnLoad  !Page.IsPostBack==true
2010-11-23 02:26:31 171: UserEventControl  OnInit
2010-11-23 02:26:31 171: UserParentPage  OnInit
2010-11-23 02:26:31 171: Default  OnInit
2010-11-23 02:26:31 171: UserParentPage  OnLoad
2010-11-23 02:26:31 171: Default   Page_Load
2010-11-23 02:26:31 171: UserEventControl  OnLoad
2010-11-23 02:26:31 171: UserEventControl  OnLoad
2010-11-23 02:26:31 171: UserEventControl  lbtnShow_Click
2010-11-23 02:26:31 171: Default   userEventControl_Changed    

 

  从前面的6句可以看出,子控件UserEventControl 的Init事件发生在UserParentPage 以及Default 的Init事件之前,而子控件UserEventControl 的Load事件发生在UserParentPage 以及Default 的Load事件之后。其中,父类UserParentPage 的事件发生在子类Default 的事件之前。

  注:

2010-11-23 02:26:29 828: UserEventControl  OnLoad
2010-11-23 02:26:29 828: UserEventControl  OnLoad  !Page.IsPostBack==true
2010-11-23 02:26:29 828: UserEventControl  OnLoad
2010-11-23 02:26:29 828: UserEventControl  OnLoad  !Page.IsPostBack==true

 

  这个地方明显有点不对劲,再反过去查看下子控件事件中的代码。发现

private void InitializeComponent()
         {
             this.lbtnShow.Click
+= new System.EventHandler(this.lbtnShow_Click);
             this.Load
+= new System.EventHandler(this.Page_Load);
         }

 

  多了这一行this.Load += new System.EventHandler(this.Page_Load); Load事件中再一次触发了子控件的Page_Load方法,因此注销掉该句。

  到此我们再看一下跟踪文件中的内容(将原有记录全清空),如下所示:

2010-11-23 02:46:11 281: UserEventControl  OnInit
2010-11-23 02:46:11 281: UserParentPage  OnInit
2010-11-23 02:46:11 281: Default  OnInit
2010-11-23 02:46:11 281: UserParentPage  OnLoad
2010-11-23 02:46:11 281: Default   Page_Load
2010-11-23 02:46:11 281: UserEventControl  OnLoad
2010-11-23 02:46:11 281: UserEventControl  OnLoad  !Page.IsPostBack==true
2010-11-23 02:46:13 265: UserEventControl  OnInit
2010-11-23 02:46:13 265: UserParentPage  OnInit
2010-11-23 02:46:13 265: Default  OnInit
2010-11-23 02:46:13 265: UserParentPage  OnLoad
2010-11-23 02:46:13 265: Default   Page_Load
2010-11-23 02:46:13 265: UserEventControl  OnLoad
2010-11-23 02:46:13 265: UserEventControl  lbtnShow_Click
2010-11-23 02:46:13 281: Default   userEventControl_Changed

 

  这里就分成了2次操作,第1次为加载显示的过程(1-7句),第2次为点击获取相应的值的过程(8-15句)。过程是差不多的,仅仅多了一个回传事件。这与上面总结的是一致的。

  总结

  通过父类、子类以及子控件之间的关系,加强对页面生命周期的理解,精简不必要的操作。通过事件和委托、视图状态能够很好的完成某些复杂的功能,具体应用本文将不再讲叙,仅仅是给读者一个引子。合理利用javascript:__doPostBack()和Request.Form["__EVENTARGUMENT"]能获得意想不到的效果。Init和Load都在每个控件上递归方式发生,但它们发生的顺序是相反的。每个子控件的Init与Unload事件在其容器引发相应的事件之前发生。容器的Load事件是在其子控件的Load事件之前发生。这个仅仅是本人以前实现的功能的一个精简版本,希望对各位有所帮助。

  源代码下载地址: PageEventProcess.rar

0
相关文章