嵌套的UpdatePanel导致父回发?

时间:2012-06-23 04:11:01

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

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

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

UserControl

   Parent UpdatePanel

   "Show" button

      ASP:Panel

         Dynamically added UserControls, each with UpdatePanels

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

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

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

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

编辑:我没有动态添加控件,而是将它们添加到标记中(这不是一个糟糕的解决方案)。因此摆脱了控件消失的问题,因为现在控件不是动态添加的,而是存在于标记中。但是,仍然会显示父UpdatePanel帖子,因为所有UserControl都会被发布而不是一个。如何只进行一次UserControl回发?另外,我想知道如果动态添加控制消失的问题怎么办?

2 个答案:

答案 0 :(得分:16)

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

所有控制树(包括UpdatePanels)必须重建,就像正常回发生命周期一样。 1 2 UpdatePanel确保仅返回呈现的(HTML)视图的部分。删除所有UpdatePanel 应该导致相同的行为,除了完整的回发。例如,只有表示嵌套UpdatePanel的HTML(可能是因为数据已更改)可能会在XHR响应中发回。

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


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

将遇到具有动态控件和嵌套UpdatePanels 的边缘情况。可能有一种很好的方法可以解决这个问题,但我在多次尝试中失败了。

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

UpdateMode="Conditional"
ChildrenAsTriggers="False"

使用“条件”UpdateMode,请确保手动指定触发控件或根据需要调用panel.Update()(尽管这会强制连接控件)。根据需要,ChildrenAsTriggers="True"也可能有效。最重要的是UpdateMode 不是“Always”,这是默认值。

切换到这种方法后,我没有问题 - 好吧,几乎没有 - 使用嵌套的UpdatePanels。

快乐的编码!


1 如果在禁用部分渲染(在ScriptManager中)的页面无法正确渲染(例如,所有请求都是完整的回发),则没有理由期望/相信它会正常工作使用UpdatePanels。

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

答案 1 :(得分:1)

我有一个类似的问题,一个重量级的ajax Gridview控件,一个HTML页面有多个UpdatePanels,有些嵌套,有些没有。

我花了3个多星期的试错,阅读,测试,调试和原型设计才能最终解决所有回发和部分回发问题。

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

与@user上面的响应类似,请确保您的UpdatePanel设置为条件,并且仅在您希望页面执行完整回发的最终或决定性控件上设置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)!因此,如果用户不在requiredfield验证器中提供数据,这会强制数据验证触发器工作并保持面板打开
  • 主要的UpdatePanel(upAction1)控制整个批次并仅保留所有回发内容,而不影响gridview(未完全显示)。

有一篇很棒的文章here,可以更好地解释它。

我希望这有助于某人