嵌套的UpdatePanel会导致父级页面进行回发吗?

11

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

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

UserControl

   Parent UpdatePanel

   "Show" button

      ASP:Panel

         Dynamically added UserControls, each with UpdatePanels
当单击Show按钮时,ASP:Panel变为可见状态,并根据某些后端逻辑动态向其中添加UserControl。每个动态添加的控件(以下简称UserControl)都有自己的启用Atlas的按钮和链接,因此它们也有UpdatePanels。目前,当我单击UserControl中的链接时,整个ASP:Panel的内容会消失,就好像正在重新呈现一样。所有动态添加的控件都会消失,调试器中也不会捕获到它们的任何单击事件。 我认为这里发生的情况是嵌套在更新面板中的控件会导致父UpdatePanel提交回传,因为它们触发“隐式”触发器。是否有一种方法使我的UserControls自主运行而不干扰包含它们的ASP:Panel?如果不行,我应该追求什么策略?如果每次在一个(可能很多)UserControl上发生事件时都必须重新呈现整个ASP:Panel,这意味着必须重新创建UserControl,这需要一些努力来创建。我还必须保留某种视图状态来重新创建它们。我对ASP.NET相对陌生,这听起来让人望而却步。如果可能的话,我宁愿从不刷新顶层UserControl和ASP:Panel,让每个动态添加的UserControl异步地触发和处理它们自己的事件。
编辑:不再动态添加控件,而是将它们添加到标记中(不错的解决方案)。 因此,消除了控件消失的问题,因为现在控件不是动态添加的,而是存在于标记中。但仍然会有父UpdatePanel提交的大量性能损耗,因为所有UserControls都被提交,而不仅仅是一个。如何使只有一个UserControl回传?另外,我想知道如何消除动态添加控件时的控件消失问题?
2个回答

20
首先要记住:UpdatePanels不会改变页面的生命周期。
所有控件树(包括UpdatePanels)必须像普通PostBack生命周期一样重建。UpdatePanels确保只返回呈现(HTML)视图的一部分。删除所有UpdatePanels应该会产生相同的行为,除了完全的PostBack。例如,仅表示嵌套UpdatePanel的HTML(可能是因为数据发生了变化)可能会在XHR响应中发送回来。
要获得“真正”的AJAX,请考虑使用Page Methods。或者,DevExpress(以及Telerik和其他公司?)提供了自己的“Callback Panels”形式,这类似于UpdatePanels,但可以绕过生命周期的某些部分(因此通常不完全支持ViewState模型或可能引入它们自己的怪癖)。

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

动态控件和嵌套的 UpdatePanels 的边缘情况将会遇到。也许有一种好的处理方式,但我在多次尝试中都失败了。

相反,对于每个更新面板,使用以下方法运行:

UpdateMode="Conditional"
ChildrenAsTriggers="False"

使用“条件”UpdateMode时,请确保手动指定触发控件或调用panel.Update()(虽然这会将控件硬编码),具体取决于需要,ChildrenAsTriggers="True"也可能有效。重要的是UpdateMode 不是默认值“Always”。

切换到这种方法后,我对嵌套的UpdatePanels几乎没有问题。

愉快的编码!


1 如果在禁用Partial Rendering(例如所有请求都是完整的postback)的情况下页面无法正确呈现,则没有理由期望/相信它将与UpdatePanels正常工作。

2 有时候,对于不会重新呈现的控件,“欺骗”控件树中昂贵的重新计算是有必要的。然而,我认为这些是高级案例,只有在性能分析表明存在特定需求时才应该执行。


3
我曾经遇到过一个类似的问题,涉及到一个复杂的ajax控件Gridview和一个包含多个UpdatePanels的HTML页面,有些嵌套着使用,有些没有。
我花费了三个星期的时间进行尝试、阅读、测试、调试和原型制作,最终解决了所有的后续请求和部分后续请求。
然而,我注意到了一种模式,它对我很有效。
就像上面@user的回答一样,确保您的UpdatePanels是有条件的,并且只针对您想要在页面上进行完整后续请求的最终或决定性控件指定asp:PostBackTrigger。我始终尽可能地使用asp:AsyncPostBackTrigger。
例如,如果您在GridView内部使用UpdatePanels,并且您希望在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不涉及Ok和Cancel按钮。这是因为我希望它们能触发到服务器端的部分回传(code-behind)
  • 嵌套的UpdatePanel(upAction2)仅仅是为了强制该面板(pnlAction)进行部分回传!因此,这强制数据验证触发器工作,并且在用户没有在requiredfield验证程序中提供数据时保持面板打开
  • 主要的UpdatePanel(upAction1)控制整个进程并将所有回传都保留在该面板内,而不影响gridview(没有完全显示)。
这里有一篇很棒的文章(链接),讲得更好。
希望这能帮助到某些人。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接