2012-09-11 85 views
0

首先,我知道我在這裏做什麼看起來完全不切實際,並不是很好的設計,但我試圖提高包含8000多行標記的ASPX的性能。由於這個頁面的複雜性(更不用說混亂)和簡短的截止日期,重寫它以使用客戶端與AJAX/JSON綁定不是一個選項,所以我必須繼續使用serverside綁定。ASP.NET WebForms:異步UpdatePanel?

我正在處理的頁面包含大約13個單獨的部分,每個部分都從數據庫加載它自己的實體。現在,頁面最初同步加載所有實體,因此您可以想象此頁面有時可能需要5秒或更長時間才能加載。我的目標是採用一種快速修復方法,只有在部分展開後才能加載這些部分,以便僅加載用戶請求的部分,從而提高性能並節省數據庫資源。

下面的示例代碼應該很容易,如果你有興趣嘗試了這一點爲自己粘貼到一個VB.NET的WebForm。只需命名頁面asyncupdatepanels.aspx

問題: 總的來說,我的解決方案工作得很好。在cmUpdate_Click中,我使用Threading.Thread.Sleep(2000)來模擬對數據庫的調用以檢索數據。當您單擊其中一個按鈕時,它會暫停2秒,然後將適當的Panel的.Visible屬性設置爲True。

當您單擊一個按鈕,然後在第一個完成更新之前單擊另一個按鈕時,會出現此問題。例如,如果單擊Show Panel 1,然後快速單擊Show Panel 2,即使在代碼隱藏中觸發了兩個按鈕點擊,也只有面板2顯示。

也許asynchronous UpdatePanel是錯誤的用語用在這裏。無論如何,我需要找到一種方法來顯示面板,就好像它們在單獨的異步線程中執行一樣。我希望能夠在幾乎同一時間點擊這些按鈕並顯示兩個面板。

如果任何人有任何其他的解決方案,我的問題,這將不需要對我綁定控件中的每個部分的方式發生重大變化,我很樂意聽到它。我現在使用的方法幾乎是一種黑客攻擊,但它現在可以工作,直到我們最終在MVC/c#中重寫這整個事情。

編輯:生產代碼實際上並不使用按鈕的OnClientClick調用Javascript函數。相反,它使用jQuery手風琴。我只是想簡化示例代碼。目前,無論最終如何調用__doPostBack("<%=cmUpdate.ClientID %>", ButtonId);,都將注意力放在__doPostBack("<%=cmUpdate.ClientID %>", ButtonId);上。

ASPX

<%@ Page Language="vb" AutoEventWireup="false" EnableEventValidation="false" CodeBehind="asyncupdatepanels.aspx.vb" Inherits="JsonJqueryDevex.asyncupdatepanels" %> 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head runat="server"> 
    <title></title> 
    <script language="javascript" type="text/javascript"> 

     function UpdateIt(ButtonId) { 
      __doPostBack("<%=cmUpdate.ClientID %>", ButtonId); 
      return false; 
     } 

    </script> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <asp:ScriptManager ID="ScriptManager1" runat="server"> 
    </asp:ScriptManager> 
    <div> 
     <asp:Button ID="cmShow1" Text="Show Panel 1" ClientIDMode="Static" OnClientClick="javascript:return UpdateIt(this.id);" runat="server" /> 
     <asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional" runat="server"> 
      <ContentTemplate> 
       <asp:Panel ID="pnl1" Visible="false" runat="server"> 
        Panel 1 content 
       </asp:Panel> 
      </ContentTemplate> 
      <Triggers> 
       <asp:AsyncPostBackTrigger ControlID="cmUpdate" EventName="Click" /> 
      </Triggers> 
     </asp:UpdatePanel> 
     <asp:Button ID="cmShow2" Text="Show Panel 2" ClientIDMode="Static" OnClientClick="javascript:return UpdateIt(this.id);" runat="server" /> 
     <asp:UpdatePanel ID="UpdatePanel2" UpdateMode="Conditional" runat="server"> 
      <ContentTemplate> 
       <asp:Panel ID="pnl2" Visible="false" runat="server"> 
        Panel 2 content 
       </asp:Panel> 
      </ContentTemplate> 
      <Triggers> 
       <asp:AsyncPostBackTrigger ControlID="cmUpdate" EventName="Click" /> 
      </Triggers> 
     </asp:UpdatePanel> 
     <div style="display: none"> 
      <asp:UpdatePanel UpdateMode="Conditional" runat="server"> 
       <ContentTemplate> 
        <asp:Button ID="cmUpdate" runat="server" /> 
       </ContentTemplate> 
      </asp:UpdatePanel> 
     </div> 
    </div> 
    </form> 
</body> 
</html> 

代碼隱藏:

Public Class asyncupdatepanels 
    Inherits System.Web.UI.Page 

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 

    End Sub 

    Private Sub cmUpdate_Click(sender As Object, e As System.EventArgs) Handles cmUpdate.Click 

     Dim Param As String = Request("__EVENTARGUMENT") 

     Threading.Thread.Sleep(2000) 

     Select Case Param 
      Case "cmShow1" 
       pnl1.Visible = True 
      Case "cmShow2" 
       pnl2.Visible = True 
     End Select 

    End Sub 
End Class 
+0

爲什麼不顯示更新進度欄,直到UpdatePanel中的內容被加載。否則,最好遵循延遲加載方法來填充內容。即動態構建這些元素 –

回答

0

如何禁用上點擊相應的按鈕?

說,

function UpdateIt(ButtonId) { 
      $('#<%=cmShow1.ClientID %>').attr('disabled', true); 
      $('#<%=cmShow2.ClientID %>').attr('disabled', true); 
      __doPostBack("<%=cmUpdate.ClientID %>", ButtonId); 
      return false; 
     } 

然後,在後面的代碼,睡眠後,再次啓用它們(cmShow1.Enabled =真/ cmShow2.Enabled = TRUE) - UpdatePanel的通話將處理其餘部分。

+0

在生產應用程序中,觸發這些部分展開的內容並不是真正的按鈕。我們使用jQuery手風琴。我使用按鈕點擊來簡化示例代碼。我會更新我的答案。 – oscilatingcretin

+0

您正在使用的手風琴是否可以從服務器端代碼訪問?實際上,它可以像我的按鈕示例一樣完成,只需單擊「Accordion」並在服務器端再次啓用「啓用」即可。 –

0

我會在您更新的面板所在的頁面的page_load事件中對您的服務器端執行AJAX調用。處理完成後,您將調用更新面板的更新方法。

您不必等待處理完成任何你想做的事情。

的JavaScript(用jQuery):

function ajaxCall() { 
    $.ajax({ 
     url: "YourPage.aspx" 
    }); 
} 

您可以處理在.NET中Page_Load您的AJAX調用。

我知道你說過使用AJAX不是一個好的選擇,但這是相當短暫和簡單的。