取消异步回发

更新:2007 年 11 月

通过使用页上的 NET UpdatePanel Web 服务器控件,可以在 ASP.NET 中实现异步回发。UpdatePanel 控件不再需要在每次回发时刷新整个页面,这样将改善用户体验。在浏览器中,Microsoft AJAX Library 中的 Sys.WebForms.PageRequestManager 类在客户端页生命周期中管理事件以进行异步回发。可以通过处理 PageRequestManager 类公开的事件来自定义异步回发出现的方式。

在本教程中,将使用 PageRequestManager 类的 initializeRequest 事件来取消当前正在执行的异步回发。

有关在 PageRequestManager 类中引发的事件序列的信息,请参见处理 PageRequestManager 事件

先决条件

若要在您自己的开发环境中实现这些过程,您需要:

  • Microsoft Visual Studio 2005 或 Microsoft Visual Web Developer 速成版。

  • 一个支持 AJAX 的 ASP.NET 网站。

创建取消回发的脚本

首先,创建用于管理浏览器中的异步回发的 ECMAScript (JavaScript) 代码。

创建 JavaScript 代码以取消回发

  1. 在 ASP.NET 网站中,添加新的 JScript 文件并将其命名为 CancelPostback.js。

  2. 向文件中添加以下脚本:

    var divElem = 'AlertDiv';
    var messageElem = 'AlertMessage';
    
    Sys.Application.add_load(ApplicationLoadHandler)
    function ApplicationLoadHandler(sender, args)
    {
         Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(CheckStatus);
    }
    function CheckStatus(sender, args)
    {
      var prm = Sys.WebForms.PageRequestManager.getInstance();
      if (prm.get_isInAsyncPostBack() & args.get_postBackElement().id == 'CancelRefresh') {
         prm.abortPostBack();
      }
      else if (prm.get_isInAsyncPostBack() & args.get_postBackElement().id == 'RefreshButton') {
         args.set_cancel(true);
         ActivateAlertDiv('visible', 'Still working on previous request.');
     }
      else if (!prm.get_isInAsyncPostBack() & args.get_postBackElement().id == 'RefreshButton') {
         ActivateAlertDiv('visible', 'Retrieving headlines.');
      }
    }
    function ActivateAlertDiv(visString, msg)
    {
         var adiv = $get(divElem);
         var aspan = $get(messageElem);
         adiv.style.visibility = visString;
         aspan.innerHTML = msg;
    }
    if(typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
    
    var divElem = 'AlertDiv';
    var messageElem = 'AlertMessage';
    
    Sys.Application.add_load(ApplicationLoadHandler)
    function ApplicationLoadHandler(sender, args)
    {
         Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(CheckStatus);
    }
    function CheckStatus(sender, args)
    {
      var prm = Sys.WebForms.PageRequestManager.getInstance();
      if (prm.get_isInAsyncPostBack() & args.get_postBackElement().id == 'CancelRefresh') {
         prm.abortPostBack();
      }
      else if (prm.get_isInAsyncPostBack() & args.get_postBackElement().id == 'RefreshButton') {
         args.set_cancel(true);
         ActivateAlertDiv('visible', 'Still working on previous request.');
     }
      else if (!prm.get_isInAsyncPostBack() & args.get_postBackElement().id == 'RefreshButton') {
         ActivateAlertDiv('visible', 'Retrieving headlines.');
      }
    }
    function ActivateAlertDiv(visString, msg)
    {
         var adiv = $get(divElem);
         var aspan = $get(messageElem);
         adiv.style.visibility = visString;
         aspan.innerHTML = msg;
    }
    if(typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
    

    该脚本执行下列任务:

    • 定义 Sys.Application 类的 load 事件的处理程序。此处理程序随后为 PageRequestManager 类的 initializeRequest 事件注册一个名为 CheckStatus 的处理程序。

    • 定义 CheckStatus 处理程序以检查当前是否正在执行一个异步回发,并确定导致该回发的元素的名称。

    • 定义一个 ActivateAlertDiv 函数,该函数切换用于显示消息的 <div> 元素的可见性。

对 UpdatePanel 控件使用脚本

在此过程中,将使用您在包含 UpdatePanel 控件的页中创建的脚本。如果用户在异步回发进行过程时单击了某个链接,则该脚本将取消回发。

创建用户可以在其中取消回发的页

  1. 创建名为 Default.aspx 的新的单文件 ASP.NET 网页并切换到“设计”视图。

  2. 在工具箱的**“AJAX Extensions”**选项卡中,双击 ScriptManager 控件以将其添加到页面中。

    UpdatePanel 教程

  3. 在工具箱中,双击 UpdatePanel 控件以将其添加到页面中。

    UpdatePanel 教程

  4. 切换到“源”视图,然后将以下样式规则添加到页的 <style> 元素中的 <style> 块中:

        <style type="text/css">
        body {
            font-family: Tahoma;
        }
        #UpdatePanel1{
           width: 400px;
           height: 200px;
           border: solid 1px gray;
        }
        div.AlertStyle {
          font-size: smaller;
          background-color: #FFC080;
          width: 400px;
          height: 20px;
          visibility: hidden;
        }
        </style>
    
        <style type="text/css">
        body {
            font-family: Tahoma;
        }
        #UpdatePanel1{
           width: 400px;
           height: 200px;
           border: solid 1px gray;
        }
        div.AlertStyle {
          font-size: smaller;
          background-color: #FFC080;
          width: 400px;
          height: 20px;
          visibility: hidden;
        }
        </style>
    

    样式规则定义由 UpdatePanel 控件呈现的 <div> 元素的高度和宽度。规则还定义显示进度消息的嵌套的 <div> 元素的外观。

  5. 在 <ContentTemplate> 元素的 <ContentTemplate> 元素内部添加以下标记:

    <asp:DataList ID="HeadlineList" runat="server">
        <HeaderTemplate>
        <strong>Headlines</strong>
        </HeaderTemplate>
        <ItemTemplate>
             <%# Eval("Value") %>
        </ItemTemplate>
        <FooterTemplate>
        </FooterTemplate>
        <FooterStyle HorizontalAlign="right" />
    </asp:DataList>
    <p style="text-align:right">
    <asp:Button ID="RefreshButton" 
                Text="Refresh" 
                runat="server" 
                OnClick="NewsClick_Handler" />
    </p>
    <div id="AlertDiv" class="AlertStyle">
    <span id="AlertMessage"></span> 
    &nbsp;&nbsp;&nbsp;&nbsp;
    <asp:LinkButton ID="CancelRefresh" runat="server">
    Cancel</asp:LinkButton>                      
    
    <asp:DataList ID="HeadlineList" runat="server">
        <HeaderTemplate>
        <strong>Headlines</strong>
        </HeaderTemplate>
        <ItemTemplate>
             <%# Eval("Value") %>
        </ItemTemplate>
        <FooterTemplate>
        </FooterTemplate>
        <FooterStyle HorizontalAlign="right" />
    </asp:DataList>
    <p style="text-align:right">
    <asp:Button ID="RefreshButton" 
                Text="Refresh" 
                runat="server" 
                OnClick="NewsClick_Handler" />
    </p>
    <div id="AlertDiv" class="AlertStyle">
    <span id="AlertMessage"></span> 
    &nbsp;&nbsp;&nbsp;&nbsp;
    <asp:LinkButton ID="CancelRefresh" runat="server">
    Cancel</asp:LinkButton>                      
    

    该标记执行以下任务:

    • 定义一个 DataList 控件,其中的项绑定到一个 Value 字段。此过程稍后会将该字段作为一个 SortedList 对象进行定义。

    • 定义导致异步回发的 Button 控件。

    • 定义一个 <div> 元素,该元素用于在异步回发过程中显示消息。<div> 元素也包括一个 LinkButton 控件,该控件可用来取消回发。

  6. 在 <script runat="server"> 元素中,添加以下服务器代码作为 Click 事件处理程序,该处理程序针对的是 UpdatePanel 控件中的**“刷新”**按钮。

    Protected Sub NewsClick_Handler(ByVal sender As Object, ByVal e As EventArgs)
        System.Threading.Thread.Sleep(2000)
        HeadlineList.DataSource = GetHeadlines()
        HeadlineList.DataBind()        
    End Sub
    
    protected void NewsClick_Handler(object sender, EventArgs e)
    {
        System.Threading.Thread.Sleep(2000);
        HeadlineList.DataSource = GetHeadlines();
        HeadlineList.DataBind();
    }
    

    该代码使用数据绑定来读取和显示 DataList 控件中的标题列表。

    Bb398789.alert_note(zh-cn,VS.90).gif说明:

    出于本教程的需要,Click 事件的处理程序有意引入了延迟。在实际应用中,您不会引入延迟。相反,延迟是由服务器通信或需要花费很长时间处理的服务器代码造成的,例如长时间运行的数据库查询。

  7. 在 <script> 元素内部,为页的 Load 事件添加下列代码:

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
        If Not (IsPostBack) Then
            HeadlineList.DataSource = GetHeadlines()
            HeadlineList.DataBind()
        End If
    End Sub
    
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            HeadlineList.DataSource = GetHeadlines();
            HeadlineList.DataBind();
        }
    }
    

    该代码检查当前请求是否为回发请求。如果该请求不是回发请求,则将 DataList 控件绑定到一个标题列表。(在异步回发期间,上一步中创建的 NewClick_Handler 方法中将发生数据绑定。)

  8. 在 <script> 元素内部,添加下列代码以生成标题:

    ' Helper method to simulate news headline fetch.
    Private Function GetHeadlines() As SortedList
        Dim headlines As New SortedList()
        headlines.Add(1, "This is headline 1.")
        headlines.Add(2, "This is headline 2.")
        headlines.Add(3, "This is headline 3.")
        headlines.Add(4, "This is headline 4.")
        headlines.Add(5, "This is headline 5.")
        headlines.Add(6, "(Last updated on " & DateTime.Now.ToString() & ")")
        Return headlines
    End Function
    
    // Helper method to simulate news headline fetch.
    private SortedList GetHeadlines()
    {
        SortedList headlines = new SortedList();
        headlines.Add(1, "This is headline 1.");
        headlines.Add(2, "This is headline 2.");
        headlines.Add(3, "This is headline 3.");
        headlines.Add(4, "This is headline 4.");
        headlines.Add(5, "This is headline 5.");
        headlines.Add(6, "(Last updated on " + DateTime.Now.ToString() + ")");
        return headlines;
    }
    

    在本教程中,这些标题是以静态列表的形式创建的。在实际的应用中,将动态生成这些标题。

  9. 切换到“设计”视图,并确保页与下图类似。

    UpdatePanel 教程

  10. 选择 ScriptManager 控件。

  11. 在“属性”窗口中,选择**“脚本”属性并单击省略号 (…) 按钮以显示“ScriptReference 集合编辑器”**对话框。

  12. 单击**“添加”**以添加脚本引用。

  13. 将脚本引用的**“路径”**属性设置为 CancelPostback.js,该文件是以前创建的 JavaScript 文件。

    使用 ScriptManagerScripts 集合添加脚本引用可确保在 Microsoft AJAX Library 加载之后加载相应的脚本。

    UpdatePanel 教程

  14. 单击**“确定”关闭“ScriptReference 集合编辑器”**对话框。

  15. 保存更改,然后按 Ctrl+F5 在浏览器中查看页面。

  16. 单击**“刷新”**按钮并等待面板刷新。

    将显示一条消息,并提供一个用于取消回发的选项。

  17. 再次单击**“刷新”按钮,然后在消息出现之后再次单击“刷新”**按钮并等待面板刷新。

    消息的文本将变为指示先前的刷新仍在进行,将忽略第二次刷新。

  18. 再次单击**“刷新”按钮,并在消息出现时单击“取消”**链接来取消回发。

    此时,由于已取消异步回发,因此 UpdatePanel 控件中显示的时间不会发生更改。

    <%@ Page Language="VB" %>
    <%@ Import Namespace="System.Collections.Generic" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <script runat="server">
        Protected Sub NewsClick_Handler(ByVal sender As Object, ByVal e As EventArgs)
            System.Threading.Thread.Sleep(2000)
            HeadlineList.DataSource = GetHeadlines()
            HeadlineList.DataBind()        
        End Sub
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
            If Not (IsPostBack) Then
                HeadlineList.DataSource = GetHeadlines()
                HeadlineList.DataBind()
            End If
        End Sub
        ' Helper method to simulate news headline fetch.
        Private Function GetHeadlines() As SortedList
            Dim headlines As New SortedList()
            headlines.Add(1, "This is headline 1.")
            headlines.Add(2, "This is headline 2.")
            headlines.Add(3, "This is headline 3.")
            headlines.Add(4, "This is headline 4.")
            headlines.Add(5, "This is headline 5.")
            headlines.Add(6, "(Last updated on " & DateTime.Now.ToString() & ")")
            Return headlines
        End Function
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head1" runat="server">
        <title>Canceling Postback Example</title>
        <style type="text/css">
        body {
            font-family: Tahoma;
        }
        #UpdatePanel1{
           width: 400px;
           height: 200px;
           border: solid 1px gray;
        }
        div.AlertStyle {
          font-size: smaller;
          background-color: #FFC080;
          width: 400px;
          height: 20px;
          visibility: hidden;
        }
        </style>
    </head>
    <body>
        <form id="form1" runat="server">
            <div >
            <asp:ScriptManager ID="ScriptManager1" runat="server">
            <Scripts>
            <asp:ScriptReference Path="CancelPostback.js" />
            </Scripts>
            </asp:ScriptManager>
            <asp:UpdatePanel  ID="UpdatePanel1" runat="Server" >
                <ContentTemplate>
                    <asp:DataList ID="HeadlineList" runat="server">
                        <HeaderTemplate>
                        <strong>Headlines</strong>
                        </HeaderTemplate>
                        <ItemTemplate>
                             <%# Eval("Value") %>
                        </ItemTemplate>
                        <FooterTemplate>
                        </FooterTemplate>
                        <FooterStyle HorizontalAlign="right" />
                    </asp:DataList>
                    <p style="text-align:right">
                    <asp:Button ID="RefreshButton" 
                                Text="Refresh" 
                                runat="server" 
                                OnClick="NewsClick_Handler" />
                    </p>
                    <div id="AlertDiv" class="AlertStyle">
                    <span id="AlertMessage"></span> 
                    &nbsp;&nbsp;&nbsp;&nbsp;
                    <asp:LinkButton ID="CancelRefresh" runat="server">
                    Cancel</asp:LinkButton>                      
                </ContentTemplate>
            </asp:UpdatePanel>
            </div>
        </form>
    </body>
    </html>
    
    <%@ Page Language="C#" %>
    <%@ Import Namespace="System.Collections.Generic" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <script runat="server">
        protected void NewsClick_Handler(object sender, EventArgs e)
        {
            System.Threading.Thread.Sleep(2000);
            HeadlineList.DataSource = GetHeadlines();
            HeadlineList.DataBind();
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                HeadlineList.DataSource = GetHeadlines();
                HeadlineList.DataBind();
            }
        }
        // Helper method to simulate news headline fetch.
        private SortedList GetHeadlines()
        {
            SortedList headlines = new SortedList();
            headlines.Add(1, "This is headline 1.");
            headlines.Add(2, "This is headline 2.");
            headlines.Add(3, "This is headline 3.");
            headlines.Add(4, "This is headline 4.");
            headlines.Add(5, "This is headline 5.");
            headlines.Add(6, "(Last updated on " + DateTime.Now.ToString() + ")");
            return headlines;
        }
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Canceling Postback Example</title>
        <style type="text/css">
        body {
            font-family: Tahoma;
        }
        #UpdatePanel1{
           width: 400px;
           height: 200px;
           border: solid 1px gray;
        }
        div.AlertStyle {
          font-size: smaller;
          background-color: #FFC080;
          width: 400px;
          height: 20px;
          visibility: hidden;
        }
        </style>
    </head>
    <body>
        <form id="form1" runat="server">
            <div >
            <asp:ScriptManager ID="ScriptManager1" runat="server">
            <Scripts>
            <asp:ScriptReference Path="CancelPostback.js" />
            </Scripts>
            </asp:ScriptManager>
            <asp:UpdatePanel  ID="UpdatePanel1" runat="Server" >
                <ContentTemplate>
                    <asp:DataList ID="HeadlineList" runat="server">
                        <HeaderTemplate>
                        <strong>Headlines</strong>
                        </HeaderTemplate>
                        <ItemTemplate>
                             <%# Eval("Value") %>
                        </ItemTemplate>
                        <FooterTemplate>
                        </FooterTemplate>
                        <FooterStyle HorizontalAlign="right" />
                    </asp:DataList>
                    <p style="text-align:right">
                    <asp:Button ID="RefreshButton" 
                                Text="Refresh" 
                                runat="server" 
                                OnClick="NewsClick_Handler" />
                    </p>
                    <div id="AlertDiv" class="AlertStyle">
                    <span id="AlertMessage"></span> 
                    &nbsp;&nbsp;&nbsp;&nbsp;
                    <asp:LinkButton ID="CancelRefresh" runat="server">
                    Cancel</asp:LinkButton>                      
                </ContentTemplate>
            </asp:UpdatePanel>
            </div>
        </form>
    </body>
    </html>
    

回顾

本教程演示如何编写用于取消异步回发的 JavaScript 代码。该脚本提供 PageRequestManager 类的 initializeRequest 事件的处理程序。在 initializeRequest 事件中,可以确定哪个元素导致了回发以及回发是否正在进行。然后可以采取相应的操作。在本教程中,代码显示一个包含取消按钮的 <div> 元素。

若要自动显示 UpdatePanel 控件状态,可以使用 UpdateProgress 控件。有关更多信息,请参见 UpdateProgress 控件介绍

请参见

任务

在客户端脚本中为 UpdateProgress 控件编程

概念

处理 PageRequestManager 事件

参考

Sys.WebForms.PageRequestManager 类

Sys.WebForms.PageRequestManager initializeRequest 事件