代码改变世界

ASP.NET客户端生命周期事件的例子代码的分析

2007-06-26 13:57  Valens  阅读(628)  评论(0编辑  收藏  举报

作者:Valens
时间:2007-06-26
我们的目标是:无蛀牙(从阅读代码到理解原理)!

之前翻译了一下微软关于《ASP.NET AJAX 客户端生命周期事件 》的一篇技术文档。一直没有时间更深入地去查看其中的示例代码。当然我还是觉得查看示例代码是很重要的。而由于我是一个记性不好的人,所以我总会记下一些我在查看代码中发现的一些个人觉得有用的信息。当然“大牛”们总是知道这些的,想必对这些已是了然于胸啊。应该还能给我一些提示,纠正我的一些错误理解。欢迎大家给我提出建议,我会积极地进行修改的。

首先是在页面中添加一个ScriptManager:
        <asp:ScriptManager ID="ScriptManager1" runat="server">
            
<Scripts>
                
<%--添加客户端脚本引用--%>
                
<asp:ScriptReference Path="ClientEventTest.js" />
            
</Scripts>
        
</asp:ScriptManager>

接着添加两个UpdatePanel控件,它们的关系是嵌套的,具体请看:
        <asp:UpdatePanel ID="OuterPanel" UpdateMode="Conditional" runat="server">
                
<ContentTemplate>
                    Postbacks from inside the outer panel and inner panel are asynchronous postbacks.
                    PRM 
= Sys.WebForms.PageRequestManager. APP = Sys.Application.
                    
<br />
                    (从父容器和子容器的回送都是异步回送。在一个UpdatePanel中内嵌了一个UpdatePanel。)
                    
<br />
                    
<br />
                    
<asp:Button ID="OPButton1" Text="Outer Panel Button(父容器按钮)" runat="server" />
                    Last updated on
                    
<%= DateTime.Now.ToString() %>
                    
<br />
                    
<br />
                    
<asp:UpdatePanel ID="NestedPanel" UpdateMode="Conditional" runat="server">
                        
<ContentTemplate>
                            
<asp:Button ID="NPButton1" Text="Nested Panel 1 Button(子容器按钮)" runat="server" />
                            Last updated on
                            
<%= DateTime.Now.ToString() %>
                            
<br />
                        
</ContentTemplate>
                    
</asp:UpdatePanel>
                    
                    
<asp:UpdatePanel ID="TestUpdatePanel" UpdateMode="Conditional" runat="server">
                        
<ContentTemplate>
                            Last updated on【又一嵌套的UpdatePanel】
                            
<%= DateTime.Now.ToString() %>
                            
<br />
                        
</ContentTemplate>
                    
</asp:UpdatePanel>
                
</ContentTemplate>
            
</asp:UpdatePanel>

这样页面的主要部分就已经添加完毕了。

接着我们看比较感兴趣的部分,当然也是最关键的ClientEventTest.js了:

首先是关于Application类的事件的具体脚本
// ******* BEGIN: Application 事件操作。*******
 // Hook up Application event handlers.【为Application事件关联操作】
 var app = Sys.Application;
 
// 添加一个Application加载事件的操作
 app.add_load(ApplicationLoad);
 
// 添加一个Application初始化事件的操作
 app.add_init(ApplicationInit);
 
// 添加一个Application释放资源事件的操作
 app.add_disposing(ApplicationDisposing);
 
// 添加一个Application卸载事件的操作
 app.add_unload(ApplicationUnload);
 
 
// Application event handlers for component developers.【适合组件开放人员调用的Application事件操作】
 // Application初始化事件,在初始化事件内调用其它事件操作
function ApplicationInit(sender) {
  
// 获取PageRequestManager实例
  var prm = Sys.WebForms.PageRequestManager.getInstance();
  
// 如果不是异步回送,则执行
  if (!prm.get_isInAsyncPostBack())
  {
      
// 为PageRequestManager的实例添加初始化请求事件的操作
      prm.add_initializeRequest(InitializeRequest);
      
// 为PageRequestManager的实例添加开始请求事件的操作
      prm.add_beginRequest(BeginRequest);
      
// 为PageRequestManager的实例添加页面正在加载事件的操作
      prm.add_pageLoading(PageLoading);
      
// 为PageRequestManager的实例添加页面已加载事件的操作
      prm.add_pageLoaded(PageLoaded);
      
// 为PageRequestManager的实例添加结束请求事件的操作
      prm.add_endRequest(EndRequest);
  }
  
// 显示当前是在Application的初始化。
  $get('ClientEvents').innerHTML += "APP:: Application init.【Application 初始化】 <br/>";
}

// Application加载事件的操作
function ApplicationLoad(sender, args) {
  $get('ClientEvents').innerHTML 
+= "APP:: Application load.【Application 加载】 ";
  
// Sys.ApplicationLoadEventArgs的实例args的get_isPartialLoad方法来检查是否部分刷新。
  // 得到当前的Load事件究竟是第一次打开触发的还是异步刷新触发的。
  $get('ClientEvents').innerHTML += "(isPartialLoad = " + args.get_isPartialLoad() + ")【是否部分刷新】<br/>";
  
/* -----------------------------------------------
   * 关于ApplicationLoadEventArgs类的isPartialLoad属性
   * 该属性的作用:返回一个页面是否部分刷新。   
   * 语法:
        var a = new Sys.ApplicationLoadEventArgs(components, isPartialLoad);
        if a.get_isPartialLoad(){};
   * 返回值意义:true 代表页面是在部分刷新; 否则返回 false.
   * 
   * 说明:(这点很重要!)
   * 要获取(get)或设置(set)客户端API的属性,必须通过以 get_ 和 set_ 为前缀的属性访问方法实现。
   * 比如要设置cancel属性,就通过 get_cancel 或 set_cancel 方法。
   * -----------------------------------------------
*/
}

// Application卸载事件的操作
function ApplicationUnload(sender) {
  alert('APP:: Application unload.【Application 卸载】');
}

// Application释放资源事件的操作
function ApplicationDisposing(sender) {
  $get('ClientEvents').innerHTML 
+= "APP:: Application disposing.【Application 释放】 <br/>";
  
}

// Application event handlers for page developers.【适合页面开放人员调用的Application事件操作】
//
 页面加载事件
/*
 说明:
 * 要操作 Application 对象的 load 和 unload 事件,不需要显示地绑定到一个操作事件。
 * 直接使用保留关键字 pageLoad 和 pageUnload 来创建一个函数 
*/
function pageLoad() {
  $get('ClientEvents').innerHTML 
+= "PAGE:: Load.【页面加载】<br/>";
}
// 页面卸载事件
function pageUnload() {
  alert('Page:: Page unload.【页面卸载】');
}
//******* END:  Application 事件操作。********

接着是PageRequestManager类的事件操作:
// BEGIN:PageRequestManager event handlers.
//
 PageRequestManager实例的初始化请求事件的操作
function InitializeRequest(sender, args) {
  $get('ClientEvents').innerHTML 
+= "<hr/>";
  $get('ClientEvents').innerHTML 
+= "PRM:: Initializing async request.【初始化异步请求】<br/>";  
}

// PageRequestManager实例的开始请求事件的操作
function BeginRequest(sender, args) {
  $get('ClientEvents').innerHTML 
+= "PRM:: Begin processing async request.【开始处理异步请求】<br/>";
}

// PageRequestManager实例的页面正在加载事件的操作
function PageLoading(sender, args) {
  $get('ClientEvents').innerHTML 
+= "PRM:: Loading results of async request.【正在加载异步请求返回的结果】<br/>";
  
// Sys.WebForms.PageLoadingEventArgs的实例args。
  var updatedPanels = printArray("PanelsUpdating", args.get_panelsUpdating());
  
var deletedPanels = printArray("PanelsDeleting", args.get_panelsDeleting());
  
/* -----------------------------------------------
   * 关于PageLoadingEventArgs类的panelsUpdating属性
   * 该属性的作用:获得在当前异步回送返回的用于重新描绘DOM中哪些UpdatePanel控件将被更新的一组HTML的<div>元素。   
   * 语法:
        var arr = eventArgs.get_panelsUpdating()
   * 返回值意义:返回一组将被更新到DOM中的<div>元素。如果没有元素需要被更新,改属性返回null。
     
     --------------------
     
   * 关于PageLoadingEventArgs类的panelsUpdating属性
   * 该属性的作用:获得在当前异步回送返回的用于描述DOM中哪些UpdatePanel控件将被删除的一组HTML的<div>元素。
   * 语法:
   *    var arr = eventArgs.get_panelsDeleted()
   * 返回值意义:一组<div>元素将从DOM中被删除。如果没有元素需要被删除,则属性返回null。
   * -----------------------------------------------
*/
  
  
// 需要更新的和删除的UpdatePanel(s)
  var message = "-->【正在更新的UpdatePanel】" + updatedPanels + "<br/>-->【正在删除的UpdatePanel】" + deletedPanels + "<br/>";
  
  document.getElementById(
"ClientEvents").innerHTML += message;
}

// PageRequestManager实例的页面已加载事件的操作
function PageLoaded(sender, args) {
  $get('ClientEvents').innerHTML 
+= "PRM:: Finished loading results of async request.【完成了加载一次异步请求的结果】<br/>";
  
// Sys.WebForms.PageLoadedEventArgs的实例args。
  var updatedPanels = printArray("PanelsUpdated", args.get_panelsUpdated());
  
var createdPanels = printArray("PaneslCreated", args.get_panelsCreated());
  
/* -----------------------------------------------
   * 关于PageLoadedEventArgs类的panelsCreated属性
   * 该属性的作用:获得在最近的一次异步回送返回的用于重新描绘DOM被更新时哪些UpdatePanel控件已经创建的一组HTML的<div>元素。
   * 语法:
        var arr = eventArgs.get_panelsCreated();
   * 返回值意义:一组<div>元素将在由最近一次异步回送引起的DOM操作过程中已创建。如果没有元素需要被删除,则属性返回null。
   * 备注:如果一个UpdatePanel控件被更新作为一个页面部份更新结果,在panelsCreated属性的一组<div>元素的引用在PageLoadedEventArgs类中有相应的引用。
            (即PageLoadedEventArgs实例中有显示哪些需要被更新的UpdatePanel数据。)
            PageRequestManager类利用一个PageLoadedEventArgs对象来返回的pageLoaded事件所需要的数据。
     
     --------------------
     
   * 关于PageLoadedEventArgs类的panelsCreated属性
   * 该属性的作用:获得在最近的一次异步回送返回的用于重新描绘DOM被更新时哪些UpdatePanel控件已经更新的一组HTML的<div>元素。
   * 语法:
        var arr = eventArgs.get_panelsUpdated()
   * 返回值意义:一组<div>元素将在由最近一次异步回送引起的DOM操作过程中已更新。如果没有元素需要被更新,则属性返回null。
   *  备注:如果一个UpdatePanel控件被更新作为一个页面部份更新结果,在panelsUpdated属性的一组<div>元素的引用在PageLoadedEventArgs类中有相应的引用。
            (即PageLoadedEventArgs实例中有显示哪些需要被更新的UpdatePanel数据。)
            PageRequestManager类利用一个PageLoadedEventArgs对象来返回的pageLoaded事件所需要的数据。
   * -----------------------------------------------
*/ 
  
var message = "-->【已经更新了的UpdatePanel】" + updatedPanels + "<br/>-->【已经创建了的UpdatePanel】" + createdPanels + "<br/>";
        
  document.getElementById(
"ClientEvents").innerHTML += message;
}

// 结束请求事件
function EndRequest(sender, args) {
  $get('ClientEvents').innerHTML 
+= "PRM:: End of async request.【一个异步请求结束】<br/>";
}

还需要两个所谓的Helper方法:
// Helper functions.例子需要,清除数据
function Clear()
{
  $get('ClientEvents').innerHTML 
= "";
}
// 打印数组
function printArray(name, arr)
{
    
var panels = name + '=+ arr.length;
    
if(arr.length > 0)
    {
        panels 
+= "(";
        
for(var i = 0; i < arr.length; i++)
        {
            
//获取了被更新的UpdatePanel控件的id
            panels += arr[i].id + ',';
        }
        panels 
= panels.substring(0, panels.length - 1);
        panels 
+= ")";
    }
    
return panels;
}

具体代码分析我都写在了代码中,希望能够对应的更直接。

最后将源码打个包,点击这里下载。