共用方式為


指定特定非同步回傳的優先順序

更新:2007 年 11 月

根據預設,當網頁同時產生多個非同步回傳時,最近產生的回傳具有較高的優先順序。在某些案例中,您可能想要為特定的非同步回傳指定優先順序,並取消其他回傳。

在此教學課程中,您將控制哪個回傳具有最高的優先順序。若要這樣做,您可以為 PageRequestManager 類別的 initializeRequest 事件建立事件處理常式。如需 PageRequestManager 類別中引發之事件順序的詳細資訊,請參閱使用 PageRequestManager 事件

必要條件

若要在自己的開發環境中實作這些程序,您需要:

  • Microsoft Visual Studio 2005 或 Microsoft Visual Web Developer Express 版。

  • 具備 AJAX 能力的 ASP.NET 網站。

建立為特定回傳項目指定優先順序的指令碼

一開始您必須建立 ECMAScript (JavaScript) 程式碼,此程式碼負責管理瀏覽器中的非同步回傳。

建立為特定回傳項目指定優先順序的指令碼

  1. 在 ASP.NET 網站中,加入 JScript 檔案並將它命名為 PostbackPrecedence.js。

  2. 將下列指令碼加入至檔案:

    Sys.Application.add_load(ApplicationLoadHandler)
    function ApplicationLoadHandler(sender, args)
    {
        if (!Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack())
        {
          Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(InitializeRequest);
        }
    }
    
    var divElem = 'AlertDiv';
    var messageElem = 'AlertMessage';
    var exclusivePostBackElement = 'Button1';
    var lastPostBackElement;
    function InitializeRequest(sender, args)
    { 
        var prm = Sys.WebForms.PageRequestManager.getInstance();
        if (prm.get_isInAsyncPostBack() && 
            args.get_postBackElement().id === exclusivePostBackElement) 
        {
            if (lastPostBackElement === exclusivePostBackElement)
            {
              args.set_cancel(true);
              ActivateAlertDiv('visible', 'A previous postback is still executing. The new postback has been canceled.');
              setTimeout("ActivateAlertDiv('hidden','')", 1500);
            }
            else if (lastPostBackElement !== exclusivePostBackElement)
            {
              prm.abortPostBack();
            }
        }
        else if (prm.get_isInAsyncPostBack() && 
                 args.get_postBackElement().id !== exclusivePostBackElement)
        {
            if (lastPostBackElement === exclusivePostBackElement)
            {
                args.set_cancel(true);
                ActivateAlertDiv('visible', 'A previous postback is still executing. The new postback has been canceled.');
                setTimeout("ActivateAlertDiv('hidden','')", 1500);
            }       
        }
        lastPostBackElement = args.get_postBackElement().id;      
    }
    
    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.add_load(ApplicationLoadHandler)
    function ApplicationLoadHandler(sender, args)
    {
        if (!Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack())
        {
          Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(InitializeRequest);
        }
    }
    
    var divElem = 'AlertDiv';
    var messageElem = 'AlertMessage';
    var exclusivePostBackElement = 'Button1';
    var lastPostBackElement;
    function InitializeRequest(sender, args)
    { 
        var prm = Sys.WebForms.PageRequestManager.getInstance();
        if (prm.get_isInAsyncPostBack() && 
            args.get_postBackElement().id === exclusivePostBackElement) 
        {
            if (lastPostBackElement === exclusivePostBackElement)
            {
              args.set_cancel(true);
              ActivateAlertDiv('visible', 'A previous postback is still executing. The new postback has been canceled.');
              setTimeout("ActivateAlertDiv('hidden','')", 1500);
            }
            else if (lastPostBackElement !== exclusivePostBackElement)
            {
              prm.abortPostBack();
            }
        }
        else if (prm.get_isInAsyncPostBack() && 
                 args.get_postBackElement().id !== exclusivePostBackElement)
        {
            if (lastPostBackElement === exclusivePostBackElement)
            {
                args.set_cancel(true);
                ActivateAlertDiv('visible', 'A previous postback is still executing. The new postback has been canceled.');
                setTimeout("ActivateAlertDiv('hidden','')", 1500);
            }       
        }
        lastPostBackElement = args.get_postBackElement().id;      
    }
    
    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 事件註冊名為 InitializeRequest 的處理常式。

    • 定義 InitializeRequest 處理常式以檢查目前是否正在執行非同步回傳,並判斷導致回傳之項目的名稱。若導致回傳的項目是您已指定為獨佔式回傳項目 (應該具有最高優先順序) 的項目,系統會透過設定 InitializeRequestEventArgs 類別的 cancel 屬性以取消新的回傳。

    • 定義 ActivateAlertDiv 函式,此函式會切換網頁上 <div> 項目的可視性,以便顯示訊息。

搭配 UpdatePanel 控制項使用指令碼

在此程序中,您將會使用您在網頁上建立的指令碼。網頁包含一個按鈕,其回傳的優先順序高於網頁上另一個按鈕之回傳的優先順序。

建立網頁以確定一個回傳的回傳具有較高的優先順序

  1. 建立新的單一檔案 ASP.NET Web 網頁,並切換到 [設計] 檢視。

  2. 在工具箱的 [AJAX 擴充功能] 索引標籤中,按兩下 ScriptManager 控制項並將它加入網頁。

  3. 按兩下 UpdatePanel 控制項兩次,將控制項的兩個執行個體加入網頁。

  4. 在每個 UpdatePanel 控制項中,從工具箱的 [標準] 索引標籤,加入 Label 控制項與 Button 控制項。

  5. 在兩個面板中將 Label 控制項的 Text 值設定為 Panel Initially Rendered。

  6. 按兩下每個 Button 控制項,為每個按鈕的 Click 事件加入處理常式。

  7. Click 處理常式加入下列指令碼,以手動方式建立延遲,然後在回傳的來源面板顯示目前時間:

    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
        System.Threading.Thread.Sleep(4000)
        Label1.Text = "Last update from server " & DateTime.Now.ToString()
    End Sub
    
    Protected Sub Button2_Click(ByVal sender As Object, ByVal e As EventArgs)
        System.Threading.Thread.Sleep(1000)
        Label2.Text = "Last update from server " & DateTime.Now.ToString()
    End Sub
    
    protected void Button1_Click(object sender, EventArgs e)
    {
        System.Threading.Thread.Sleep(4000);
        Label1.Text = "Last update from server " + DateTime.Now.ToString();        
    }
    
    protected void Button2_Click(object sender, EventArgs e)
    {
        System.Threading.Thread.Sleep(1000);
        Label2.Text = "Last update from server " + DateTime.Now.ToString();        
    }
    
    注意事項:

    在此教學課程中,我們刻意為 Click 事件的處理常式加入延遲。實際上,延遲並非由您造成。此延遲是因伺服器流量或需要長時間執行的伺服端程式碼 (例如,需長時間執行的資料庫查詢) 所造成。

  8. 切換至 [原始碼] 檢視,然後在網頁的<head> 項目加入下列 <style> 區塊:

        <style type="text/css">
        body {
            font-family: Tahoma;
        }
        #UpdatePanel1, #UpdatePanel2 {
          width: 400px;
          height: 100px;
          border: solid 1px gray;
        }
        div.MessageStyle {
          background-color: #FFC080;
          top: 95%;
          left: 1%;
          height: 20px;
          width: 600px;
          position: absolute;
          visibility: hidden;
        }
        </style>
    
        <style type="text/css">
        body {
            font-family: Tahoma;
        }
        #UpdatePanel1, #UpdatePanel2 {
          width: 400px;
          height: 100px;
          border: solid 1px gray;
        }
        div.MessageStyle {
          background-color: #FFC080;
          top: 95%;
          left: 1%;
          height: 20px;
          width: 600px;
          position: absolute;
          visibility: hidden;
        }
        </style>
    

    樣式規則會定義 <div> 項目的大小,此項目是由 UpdatePanel 控制項以及警告使用者何時取消回傳的 <div> 項目所呈現。

  9. 將下列標記加入網頁的 <form> 項目:

    <div id="AlertDiv" class="MessageStyle">
    <span id="AlertMessage"></span>
    </div>
    
    <div id="AlertDiv" class="MessageStyle">
    <span id="AlertMessage"></span>
    </div>
    

    標記會定義 <div> 項目,此項目會在取消非同步回傳 (由於另一個回傳已經在執行中) 時顯示訊息。

  10. 切換至 [設計] 檢視。

  11. 在第一個 UpdatePanel 控制項內按一下,然後從工具箱的 [AJAX 擴充功能] 索引標籤,加入 UpdateProgress 控制項。

  12. UpdateProgress 控制項內按一下,然後輸入 Panel1 正在更新 …。

    這會設定 ProgressTemplate 屬性。

  13. 選取 UpdateProgress 控制項,然後在 [屬性] 視窗中,將 AssociatedUpdatePanelID 屬性設定為 UpdatePanel1。

    設計工具中的網頁看起來會像下圖:

  14. 在第二個 UpdatePanel 控制項內按一下,然後加入第二個 UpdateProgress 控制項。

  15. UpdateProgress 控制項內按一下,然後輸入 Panel2 正在更新 …。

    這會設定 ProgressTemplate 屬性。

  16. 選取 UpdateProgress 控制項,然後在 [屬性] 視窗中,將 AssociatedUpdatePanelID 屬性設定為 UpdatePanel2。

    設計工具中的網頁看起來會像下圖:

  17. 選取 ScriptManager 控制項。

  18. 在 [屬性] 視窗中,選取 [指令碼] 屬性,然後按一下省略符號 (…) 按鈕以顯示 [指令碼參考集合編輯器] 對話方塊。

  19. 按一下 [加入] 以加入指令碼參考。

  20. 將指令碼參考的 [Path] 屬性設定為 PostbackPrecedence.js,這是您先前建立的 JavaScript 檔案。

    使用 ScriptManagerScripts 集合加入指令碼參考,確保指令碼可於載入 Microsoft AJAX Library 後載入。

  21. 按一下 [確定] 關閉 [指令碼參考集合編輯器] 對話方塊。

  22. 儲存變更,然後按 CTRL+F5 在瀏覽器中檢視頁面。

  23. 按一下第一個面板中的按鈕,然後按一下第二個面板中的按鈕。

    此時會顯示訊息,表示新的回傳已取消。第一個面板中的按鈕必須在啟始新的回傳之前完成。指令碼檔案提供邏輯以強制此行為。

  24. 按一下第二個面板中的按鈕,然後按一下第一個面板中的按鈕。

    第二個面板中的按鈕不會取得優先順序,因為並未在指令碼檔案中撰寫這樣的程式碼。因此,不會顯示任何警告訊息,而且會由第一個面板中的按鈕啟始新的回傳。這是非同步回傳的預設行為,也就是最近的回傳具有較高的優先順序。

    <%@ Page Language="VB" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <script >
        Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
            System.Threading.Thread.Sleep(4000)
            Label1.Text = "Last update from server " & DateTime.Now.ToString()
        End Sub
    
        Protected Sub Button2_Click(ByVal sender As Object, ByVal e As EventArgs)
            System.Threading.Thread.Sleep(1000)
            Label2.Text = "Last update from server " & DateTime.Now.ToString()
        End Sub
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head1" >
        <title>Postback Precedence Example</title>
        <style type="text/css">
        body {
            font-family: Tahoma;
        }
        #UpdatePanel1, #UpdatePanel2 {
          width: 400px;
          height: 100px;
          border: solid 1px gray;
        }
        div.MessageStyle {
          background-color: #FFC080;
          top: 95%;
          left: 1%;
          height: 20px;
          width: 600px;
          position: absolute;
          visibility: hidden;
        }
        </style>
    </head>
    <body>
        <form id="form1" >
            <div>
                <asp:ScriptManager ID="ScriptManager1" >
                <Scripts>
                <asp:ScriptReference Path="PostBackPrecedence.js" />
                </Scripts>
                </asp:ScriptManager>
                <asp:UpdatePanel  ID="UpdatePanel1" UpdateMode="Conditional" runat="Server" >
                    <ContentTemplate>
                    <strong>UpdatePanel 1</strong><br />
    
                    This postback takes precedence.<br />
                    <asp:Label ID="Label1" >Panel initially rendered.</asp:Label><br />
                    <asp:Button ID="Button1"  Text="Button" OnClick="Button1_Click" />&nbsp;
                    <asp:UpdateProgress ID="UpdateProgress1"  AssociatedUpdatePanelID="UpdatePanel1">
                    <ProgressTemplate>
                    Panel1 updating...
                    </ProgressTemplate>
                    </asp:UpdateProgress>
                    </ContentTemplate>
                </asp:UpdatePanel>
                <asp:UpdatePanel  ID="UpdatePanel2" UpdateMode="Conditional" runat="Server" >
                    <ContentTemplate>
                    <strong>UpdatePanel 2</strong><br />
                    <asp:Label ID="Label2" >Panel initially rendered.</asp:Label><br />
                    <asp:Button ID="Button2"  Text="Button" OnClick="Button2_Click" />
                    <asp:UpdateProgress ID="UpdateProgress2"  AssociatedUpdatePanelID="UpdatePanel2">
                    <ProgressTemplate>
                    Panel2 updating...
                    </ProgressTemplate>
                    </asp:UpdateProgress>
                    </ContentTemplate>
                </asp:UpdatePanel>
               <div id="AlertDiv" class="MessageStyle">
               <span id="AlertMessage"></span>
               </div>
            </div>
        </form>
    </body>
    </html>
    
    <%@ Page Language="C#" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <script >
        protected void Button1_Click(object sender, EventArgs e)
        {
            System.Threading.Thread.Sleep(4000);
            Label1.Text = "Last update from server " + DateTime.Now.ToString();        
        }
    
        protected void Button2_Click(object sender, EventArgs e)
        {
            System.Threading.Thread.Sleep(1000);
            Label2.Text = "Last update from server " + DateTime.Now.ToString();        
        }
    </script>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head1" >
        <title>Postback Precedence Example</title>
        <style type="text/css">
        body {
            font-family: Tahoma;
        }
        #UpdatePanel1, #UpdatePanel2 {
          width: 400px;
          height: 100px;
          border: solid 1px gray;
        }
        div.MessageStyle {
          background-color: #FFC080;
          top: 95%;
          left: 1%;
          height: 20px;
          width: 600px;
          position: absolute;
          visibility: hidden;
        }
        </style>
    </head>
    <body>
        <form id="form1" >
            <div>
                <asp:ScriptManager ID="ScriptManager1" >
                <Scripts>
                <asp:ScriptReference Path="PostBackPrecedence.js" />
                </Scripts>
                </asp:ScriptManager>
                <asp:UpdatePanel  ID="UpdatePanel1" UpdateMode="Conditional" runat="Server" >
                    <ContentTemplate>
                    <strong>UpdatePanel 1</strong><br />
    
                    This postback takes precedence.<br />
                    <asp:Label ID="Label1" >Panel initially rendered.</asp:Label><br />
                    <asp:Button ID="Button1"  Text="Button" OnClick="Button1_Click" />&nbsp;
                    <asp:UpdateProgress ID="UpdateProgress1"  AssociatedUpdatePanelID="UpdatePanel1">
                    <ProgressTemplate>
                    Panel1 updating...
                    </ProgressTemplate>
                    </asp:UpdateProgress>
                    </ContentTemplate>
                </asp:UpdatePanel>
                <asp:UpdatePanel  ID="UpdatePanel2" UpdateMode="Conditional" runat="Server" >
                    <ContentTemplate>
                    <strong>UpdatePanel 2</strong><br />
                    <asp:Label ID="Label2" >Panel initially rendered.</asp:Label><br />
                    <asp:Button ID="Button2"  Text="Button" OnClick="Button2_Click" />
                    <asp:UpdateProgress ID="UpdateProgress2"  AssociatedUpdatePanelID="UpdatePanel2">
                    <ProgressTemplate>
                    Panel2 updating...
                    </ProgressTemplate>
                    </asp:UpdateProgress>
                    </ContentTemplate>
                </asp:UpdatePanel>
               <div id="AlertDiv" class="MessageStyle">
               <span id="AlertMessage"></span>
               </div>
            </div>
        </form>
    </body>
    </html>
    

檢閱

此教學課程說明如何在另一個非同步回傳開始之前,讓指定的非同步回傳具有較高的優先順序 (亦即,完成處理)。強制此行為的邏輯是撰寫在包含為網頁之指令碼參考的 JavaScript 檔案中。您可以自訂指令碼,指定必須完成目前所有的非同步回傳,才能開始新的回傳。不過,在指定哪些回傳具有最高的優先順序時,應該仔細考量您的設計。

請參閱

概念

使用 PageRequestManager 事件

參考

Sys.WebForms.PageRequestManager 類別

initializeRequest