12

我的印象是嵌套 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 回发?另外,我想知道如何摆脱动态添加控件消失的问题?

4

2 回答 2

18

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

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

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


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

遇到具有动态控件和嵌套 UpdatePanel 的边缘情况。可能有一种很好的方法来处理这个问题,但我在多次不同的尝试中都失败了。

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

UpdateMode="Conditional"
ChildrenAsTriggers="False"

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

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

快乐编码!


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

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

于 2012-06-23T05:06:45.927 回答
3

Gridview我在繁重的 ajax控件和带有多个UpdatePanels、一些嵌套、一些没有的 HTML 页面上遇到了类似的问题。

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

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

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

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

IE

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

这里有一篇很棒的文章,它更好地解释了它。

我希望这可以帮助别人

于 2016-07-06T01:08:57.653 回答