2012-06-23 15 views
9

Ich habe den Eindruck, dass ein Steuerelement in einem geschachtelten UpdatePanel das UpdatePanel auf der obersten Ebene aktualisiert (und somit beide UpdatePanels aktualisiert), da alle Ereignisse auf diesem Steuerelement als "impliziter" Auslöser fungieren. Ist das korrekt?Verschachtelte UpdatePanel führt Eltern zum Postback?

Ich habe auf Draht so etwas wie dies versucht Up-

UserControl 

    Parent UpdatePanel 

    "Show" button 

     ASP:Panel 

     Dynamically added UserControls, each with UpdatePanels 

Wenn die Schaltfläche Anzeigen geklickt wird, die ASP: Panel wird sichtbar und startet Benutzersteuerelemente zu sich selbst hinzufügen, dynamisch basierend auf einigen Back-End Logik.

Jedes der dynamisch hinzugefügten Steuerelemente (im Folgenden: UserControls) verfügt über eigene ATLAS-fähige Schaltflächen und Links, sodass sie auch über UpdatePanels verfügen. Derzeit, wenn ich auf einen Link in einem der UserControls klicke, verschwindet der gesamte Inhalt des ASP: Panels, als würde es wieder gerendert werden. Alle meine dynamisch hinzugefügten Steuerelemente verschwinden und keines ihrer Klickereignisse wird im Debugger abgefangen.

Ich nehme an, was hier passiert, ist, dass Steuerelemente, die in geschachtelten Update-Panels liegen, das Eltern-UpdatePanel zurück schreiben, weil sie "implizite" Trigger auslösen. Gibt es eine Möglichkeit für meine UserControls, autonom zu arbeiten und sich nicht mit dem ASP zu messen: Panel, das sie enthält?

Wenn nicht, welche Strategie sollte ich hier verfolgen? Wenn ich das gesamte ASP: Panel jedes Mal neu rendern muss, wenn ein Ereignis auf einem der (möglicherweise vielen) UserControls auftritt, muss ich die UserControls neu erstellen, was ein wenig Aufwand erfordert. Ich muss auch eine Art von Ansichtszustand bewahren, um sie wiederherzustellen. Ich bin etwas neu in ASP.NET und das klingt einschüchternd. Ich würde lieber nie die obere Ebene UserControl und ASP: Panel aktualisieren, wenn ich es vermeiden kann, und lassen Sie jede der dynamisch hinzugefügten UserControls ihre eigenen Ereignisse asynchron auslösen und behandeln.

EDIT: Anstatt die Steuerelemente dynamisch hinzuzufügen, habe ich sie zum Markup hinzugefügt (keine schlechte Lösung). So wurde das Problem des Verschwindens von Steuerelementen beseitigt, da die Steuerelemente jetzt nicht dynamisch hinzugefügt werden, sondern stattdessen im Markup vorhanden sind. Aber immer noch ist die übergeordnete UpdatePanel-Veröffentlichung ein großer Leistungserfolg, da alle UserControls statt einer eins gebucht werden. Wie mache ich nur ein UserControl Postback? Außerdem würde ich gerne wissen, wie man das Problem des Verschwindens von Steuerelementen loswird, wenn es dynamisch hinzugefügt wird?

Antwort

14

Zunächst einmal, bedenken Sie: UpdatePanels nicht den Lebenszyklus einer Seite ändern.

Der gesamte Kontrollbaum (einschließlich der UpdatePanels) muss genauso rekonstruiert werden wie mit einem normalen Postback-Lebenszyklus. Die UpdatePanels stellen sicher, dass nur ein Teil der gerenderten (HTML) Ansicht zurückgegeben wird. Das Entfernen aller UpdatePanels sollte ergeben das gleiche Verhalten, außer mit einem vollen Postback. Zum Beispiel könnte nur der HTML-Code, der ein geschachteltes UpdatePanel darstellt (vermutlich weil Daten geändert wurden), in der XHR-Antwort zurückgesendet werden.

Um "wahr" AJAX zu bekommen, betrachten Sie Page Methoden. Alternativ bieten DevExpress (und vielleicht Telerik und andere?) Ihre eigene Form von "Callback Panels", die UpdatePanels ähnlich sind, aber Teile des Lebenszyklus umgehen können (und daher das ViewState-Modell oft nicht vollständig unterstützen) oder können ihre eigenen Macken einführen).


Zwar nicht die oben zu verstehen, ist der wahrscheinlichste Grund für die Kontrollen „zu verschwinden“, hier ist meine Regel: Lassen Sie sich nicht [Nested] Update Work „Automatisch“.

Edge Fällen mit dynamischen Steuerelementen und verschachtelten UpdatePanels wird angetroffen werden. Es könnte einen guten Weg geben, damit umzugehen, aber ich habe bei mehreren verschiedenen Versuchen versagt.

Stattdessen für jeden Update-Panel, lief mit:

UpdateMode="Conditional" 
ChildrenAsTriggers="False" 

Mit der "Conditional" Updatemode, stellen Sie sicher, manuell die Trigger-Steuerung zu spezifizieren oder panel.Update() nennen (obwohl dies schwer Drähte die Control) nach Bedarf. Je nach Bedarf ChildrenAsTriggers="True" könnte genauso gut funktionieren. Die große Sache ist, dass Update ist nicht „Always“, das ist die Standardeinstellung.

Nach dem Wechsel zu diesem Ansatz habe ich kein Problem - nun, fast keine - mit verschachtelten UpdatePanels.

Glückliche Codierung!


Wenn die Seite nicht korrekt dargestellt, wo Partial Rendering (in dem Script) deaktiviert ist (zB alle Anfragen sind voll Postbacks), dann gibt es keinen Grund zu erwarten/glaubt, wird es richtig mit UpdatePanels.

Es gibt Zeiten, in denen es gerechtfertigt ist, teure Neuberechnung im Kontrollbaum für Steuerelemente zu "betrügen", die nicht erneut gerendert werden. Ich würde jedoch diese fortgeschrittenen Fälle berücksichtigen, die nur durchgeführt werden sollten, wenn die Leistungsanalyse einen spezifischen Bedarf anzeigt.

0

Ich hatte ein ähnliches Problem mit einem schweren Ajax Gridview Steuerelement, und eine HTML-Seite mit mehreren UpdatePanels, einige verschachtelte, einige nicht.

Es dauerte über 3 Wochen von Versuch und Irrtum, Lesen, Testen, Debuggen und Prototyping bis schließlich alle Post Rücken und partielle Postbacks zu lösen.

Allerdings habe ich ein Muster feststellen, die für mich gearbeitet.

Wie die Antwort von @user oben, stellen Sie sicher, dass Ihre UpdatePanels Conditional und nur asp:PostBackTrigger auf das endgültige oder entscheidende Steuerelement festgelegt sind, auf dem die Seite einen vollständigen Postback ausführen soll. Ich verwende immer asp:AsyncPostBackTrigger wo immer möglich.

Wenn Sie beispielsweise UpdatePanels in einer GridView verwenden und ein Popup in einer Zelle der Gridview-Zeile wünschen, müssen Sie ein geschachteltes UpdatePanel verwenden.

dh

<asp:TemplateField HeaderText="Actions &amp; Communications"> 
    <ItemTemplate> 
     <asp:UpdatePanel ID="upAction1" runat="server" UpdateMode="Conditional"> 
      <Triggers> 
       <asp:AsyncPostBackTrigger ControlID="btnActionOK" /> 
      </Triggers> 
      <ContentTemplate> 
... 
... 
          <ajaxToolkit:ModalPopupExtender ID="ajaxMPE" runat="server" 
           BackgroundCssClass="modalBackground" 
           PopupControlID="upAction2" 
           TargetControlID="btnADDaction"> 
          </ajaxToolkit:ModalPopupExtender> 
          <asp:UpdatePanel ID="upAction2" runat="server" UpdateMode="Conditional"> 
           <ContentTemplate> 
            <asp:Panel ID="pnlACTION" runat="server" CssClass="pnlACTION"> 
             <div id="divHDR"> 
              <asp:Label ID="lblActionHdr" runat="server">** header **</asp:Label> 
             </div> 
             <div id="divBOD"> 
              <table style="width: 98%; text-align:left"> 
               <tr> 
                <td colspan="2"> 
                Please enter action item:<br /> 
                 <asp:TextBox ID="txtAction" runat="server" ValidationGroup="vgAction" TextMode="MultiLine" Rows="3" Width="98%"></asp:TextBox> 
                 <asp:RequiredFieldValidator ID="rfvAction" runat="server" ControlToValidate="txtAction" ValidationGroup="vgAction" 
                  ErrorMessage="* Required" SetFocusOnError="True"></asp:RequiredFieldValidator></td> 
               </tr> 
               <tr> 
                <td colspan="2"> 
                Select staff assigned to this task:<br /> 
                 <asp:DropDownList ID="ddlActionStaff" runat="server" AppendDataBoundItems="true" ValidationGroup="vgAction" /> 
                 <asp:RequiredFieldValidator ID="rfvStaff" runat="server" ControlToValidate="ddlActionStaff" InitialValue="0" ValidationGroup="vgAction" 
                  ErrorMessage="* Required" SetFocusOnError="True" Width="98%"></asp:RequiredFieldValidator></td> 
               </tr> 
               <tr> 
                <td colspan="2" style="text-align: center"> 
                  <asp:Button ID="btnActionOK" runat="server" Text="OK" OnClick="btnActionOK_Click" ValidationGroup="vgAction" CausesValidation="false" /> 
                  <asp:Button ID="btnActionCANCEL" runat="server" Text="CANCEL" OnClick="btnActionCANCEL_Click" ValidationGroup="vgAction" CausesValidation="false" /> 
                </td> 
               </tr> 
              </table> 
             </div> 
            </asp:Panel> 
           </ContentTemplate> 
          </asp:UpdatePanel> 
         </td> 
        </tr> 
       </table> 
       <asp:SqlDataSource ID="sdsTETactions" runat="server" ConnectionString="<%$ ConnectionStrings:ATCNTV1ConnectionString %>" 
... 
... 
       </asp:SqlDataSource> 
      </ContentTemplate> 
     </asp:UpdatePanel> 
    </ItemTemplate> 
    <ItemStyle HorizontalAlign="Center" /> 
</asp:TemplateField> 

Hinweis ein paar Dinge hier:

  • Die ModalPopupExtender zum Ok bezieht sich nicht und Schaltflächen Abbrechen.Das liegt daran, dass ich möchte, dass sie ein teilweises Postback auf den Server auslösen (code-behind)
  • Das verschachtelte UpdatePanel (upAction2) dient lediglich dazu, ein teilweises Postback nur für dieses Panel zu erzwingen (pnlAction)! Daher erzwingt dies die Aktivierung der Datenvalidierungstrigger und hält das Panel geöffnet, wenn der Benutzer keine Daten in den erforderlichen Feldvalidatoren bereitstellt
  • Das Haupt-UpdatePanel (upAction1) steuert das gesamte Los und behält alle Postbacks, die innerhalb dieses Panels gehalten werden, für NICHT relevant die Gitteransicht (nicht vollständig dargestellt).

Es gibt einen tollen Artikel here, der es besser erklärt.

Ich hoffe, das hilft jemandem

Verwandte Themen