【问题标题】:Nested UpdatePanel causes parent to postback?嵌套的 UpdatePanel 导致父级回发?
【发布时间】:2012-06-25 09:03:01
【问题描述】:

我的印象是嵌套 UpdatePanel 中的控件将导致顶级 UpdatePanel 刷新(从而刷新两个 UpdatePanel),因为该控件上的任何事件都充当“隐式”触发器。对吗?

我一直在尝试连接这样的东西-

UserControl

   Parent UpdatePanel

   "Show" button

      ASP:Panel

         Dynamically added UserControls, each with UpdatePanels

当单击 Show 按钮时,ASP:Panel 变为可见并开始根据一些后端逻辑动态地将 UserControls 添加到自身。

每个动态添加的控件(以下简称:UserControls)都有自己的支持 Atlas 的按钮和链接,因此它们也有 UpdatePanel。目前,当我单击其中一个 UserControls 中的链接时,ASP:Panel 的全部内容都会消失,就好像它正在重新渲染一样。我所有动态添加的控件都消失了,并且它们的点击事件都没有被调试器捕获。

我假设这里发生的情况是驻留在嵌套更新面板中的控件导致父 UpdatePanel 回发,因为它们正在触发“隐式”触发器。有没有办法让我的 UserControls 自主操作,而不会弄乱包含它们的 ASP:Panel?

如果不是,我应该在这里采取什么策略?如果每次在一个(可能很多)UserControls 上发生事件时我都必须重新渲染整个 ASP:Panel,这意味着我将不得不重新创建 UserControls,这需要花费一些精力来创建。我还必须保留某种视图状态来重新创建它们。我对 ASP.NET 有点陌生,这听起来很吓人。如果可以避免的话,我宁愿永远不要刷新顶层 UserControl 和 ASP:Panel,并让每个动态添加的 UserControl 触发并异步处理它们自己的事件。

编辑:我没有动态添加控件,而是将它们添加到标记中(不是一个糟糕的解决方案)。所以摆脱了控件消失的问题,因为现在控件不是动态添加而是存在于标记中。但仍然是父 UpdatePanel 发布对性能造成很大影响,因为所有 UserControls 都被发布而不是一个。如何只进行一次 UserControl 回发?另外,我想知道如何解决动态添加控件消失的问题?

【问题讨论】:

    标签: asp.net asp.net-ajax nested updatepanel


    【解决方案1】:

    首先,请记住:UpdatePanel不会改变页面的生命周期。

    所有的控制树(包括更新面板)必须像正常的回发生命周期一样重建。12 sup> UpdatePanel 确保只返回渲染 (HTML) 视图的部分。删除所有 UpdatePanel应该会导致 相同的行为,但完整的回发除外。例如,只有表示嵌套 UpdatePanel 的 HTML(可能是因为数据已更改)可能会在 XHR 响应中发回。

    要获得“真正的”AJAX,请考虑页面方法。或者,DevExpress(也许还有 Telerik 和其他人?)提供他们自己的“回调面板”形式,类似于 UpdatePanel,但可以绕过部分生命周期(因此通常不完全支持 ViewState 模型或者可能会介绍他们自己的怪癖)。


    虽然不理解上述内容是控件“消失”的最可能原因,但我的规则是:不要让 [嵌套] 更新面板“自动”工作。

    将遇到带有动态控件和嵌套更新面板的边缘情况。可能有一种很好的方法来处理这个问题,但我多次尝试都失败了。

    相反,对于每个更新面板,运行:

    UpdateMode="Conditional"
    ChildrenAsTriggers="False"
    

    使用“条件”更新模式,请确保手动指定触发控件或根据需要调用panel.Update()(尽管这会硬连接控件)。根据需要ChildrenAsTriggers="True" 也可以工作。最重要的是 UpdateMode 不是默认的“始终”。

    切换到这种方法后,我对嵌套的 UpdatePanel 没有任何问题——嗯,几乎没有

    编码愉快!


    1 如果页面在部分渲染(在 ScriptManager 中)被禁用(例如所有请求都是完整回发)的情况下不能正确渲染,那么没有理由期望/相信它会正常工作使用更新面板。

    2 有时可以保证在控制树中“欺骗”昂贵的重新计算,以获得不会重新渲染的控件。但是,我会考虑这些仅在性能分析表明存在特定需求时才应执行的高级案例。

    【讨论】:

      【解决方案2】:

      我有一个类似的问题,有一个沉重的 ajax Gridview 控件,以及一个带有多个 UpdatePanels 的 HTML 页面,有些是嵌套的,有些不是。

      我花了 3 多周的时间反复试验、阅读、测试、调试和原型设计,最终解决了所有回发和部分回发。

      但是我确实注意到了一种对我有用的模式。

      与上面的@user 响应一样,确保您的 UpdatePanel 设置为 Conditional,并且仅在您希望页面执行完整回发的最终或决定性控件上指定 asp:PostBackTrigger。我总是尽可能使用asp:AsyncPostBackTrigger

      因此,例如,如果您在 GridView 中使用 UpdatePanel,并且希望在 gridview 所在行的单元格中弹出窗口,那么您需要使用嵌套的 UpdatePanel。

       <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>
      

      请注意以下几点:

      • ModalPopupExtender 不引用“确定”和“取消”按钮。这是因为我希望他们触发部分回发到服务器(代码隐藏)
      • 嵌套的 UpdatePanel (upAction2) 纯粹是为了强制仅在该面板上进行部分回发 (pnlAction)!因此,如果用户未在必填字段验证器中提供数据,这将强制数据验证触发器工作并保持面板打开
      • 主 UpdatePanel (upAction1) 控制整个批次,并将所有回发仅保留在该面板中,不影响 gridview(未完全显示)。

      有一篇很棒的文章here,解释得更好。

      我希望这对某人有所帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-21
        • 2020-06-29
        • 1970-01-01
        • 2010-12-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多