【问题标题】:lazy loading asp.net Ajax Control Toolkit accordion延迟加载 asp.net Ajax Control Toolkit 手风琴
【发布时间】:2011-08-26 12:23:20
【问题描述】:

我正在使用 asp.net Ajax Control Toolkit 手风琴 (http://www.asp.net/ajaxlibrary/act_Accordion.ashx),每个手风琴窗格都包含大量信息。

所有这些信息都在页面中生成,但没有显示,因为工具包为非活动窗格提供了一个

 (style="display:none;)

但是因为信息在页面中,所以加载起来就变成了一个很重的页面。

我正在寻找一种按需加载窗格的方法:因此,只有当用户单击窗格时,才会发送 ajax 请求并加载和展开窗格。

可以用这个控件来完成,还是我应该选择不同的手风琴?任何帮助或建议表示赞赏。

更新 目前,Accordion 是用两个嵌套的中继器创建的。第一个转发器循环遍历类别并为每个类别创建一个面板。第二个重复器在每个面板内重复获取一个类别的内容并创建面板的内容。

普伦

【问题讨论】:

  • 你检查过 JQuery Accordian 吗?这可能更适合您想要完成的任务。

标签: asp.net ajax ajaxcontroltoolkit


【解决方案1】:

看看 DevExpressASPxNavBar 控件(免费 ASPxperience Suite 的一部分)。如果 ASPxNavBar 的 EnableCallBacks 属性设置为 true,则折叠组的内容不会在客户端显示。当一个组第一次展开时,它的内容会从服务器中检索出来,然后缓存在客户端上。下次扩展组时,从客户端获取其内容,不执行对服务器的回调。

查看ASPxNavBar - Callbacks (AJAX) 在线演示了解更多信息。

【讨论】:

    【解决方案2】:

    我可以向您建议的只是将链接按钮添加到您的标题和面板到您的窗格:

            <Panes>
                <asp:AccordionPane ID="First" runat="server">
                    <Header>
                        <asp:LinkButton CommandName="ASD2" ID="LinkButton2" runat="server">LinkButton</asp:LinkButton>
                    </Header>
                    <Content>
                        <asp:Panel ID="Panel2" runat="server" Visible="true">
                             First
                        </asp:Panel>
                    </Content>
                </asp:AccordionPane>
                <asp:AccordionPane ID="Second" runat="server">
                    <Header>
                        <asp:LinkButton CommandName="ASD" ID="LinkButton1" runat="server">LinkButton</asp:LinkButton>
                    </Header>
                    <Content>
                        <asp:Panel ID="Panel1" runat="server" Visible="false">
                             Second
                        </asp:Panel>
                    </Content>
                </asp:AccordionPane>
            </Panes>
    

    并在Accordion1_ItemCommand中设置相应面板的Visible属性。

    protected void Accordion1_ItemCommand(object sender, CommandEventArgs e)
    

    【讨论】:

    • 感谢您的想法。 Visible = false 的面板如何在浏览器中呈现?是不是渲染出来的。这也会导致回发吗?
    • Visible = false 的面板不会在服务器上呈现。是的,它会产生回调。您应该为部分页面重绘添加一些逻辑。
    【解决方案3】:

    我没有评论和问你问题的要点。对不起。 :(
    我的问题是关于您计划如何创建和填充手风琴。

    您将在 IDE 中使用标记手动创建窗格,还是将 Accordion 绑定到将动态创建所需窗格的 DataSource?

    您是否有 3 个单独的数据源或以下的不同组合:
    1.) DataSource 初始化面板数量并仅填充面板的 Header 信息。
    2.) DataSource 在首次加载时填充所有面板的静态内容。
    3.) DataSource 填充用户单击展开的单个面板的延迟加载内容。

    有了你的答案,我希望用一个真实的答案来更新这个答案。谢谢。

    更新:这可以通过 Ajax Control Toolkit 的 Accordion 实现的。
    我在下面有一些 very 基本代码作为概念证明。它可能会更流畅,但如果您认为有必要,我会留给您使用 UpdatingProgress 控件添加“正在加载”图像。

    Aspx 标记中的手风琴:
    (请注意 UpdatePanel - 如果需要,您可以用回调替换它们,我只是想让答案简单)

    <asp:Accordion ID="acc_Accordion" runat="server" RequireOpenedPane="false" 
            SelectedIndex="-1" onitemcommand="acc_Accordion_ItemCommand" >
        <HeaderTemplate>
            <asp:UpdatePanel ID="up_UpdateHeader" runat="server">
                <ContentTemplate>
                <%--When using "Eval" inside strings for Asp.net controls,
                    you MUST wrap them in apostrophes ('),
                    otherwise with (") you will get parser errors!--%>
                <asp:LinkButton ID="btn_Header" runat="server"
                     Text='<%# Eval("HeaderText") %>'
                     CommandName="UpdatePane" CommandArgument='<%# Eval("ItemID") %>'
                     Font-Underline="false" ForeColor="Black"
                     style="width:100%; height:100%; cursor:pointer;"/>
                     <%--Use Cursor:Pointer to keep a consistent
                         interface after disabling the button.--%>
                </ContentTemplate>
            </asp:UpdatePanel>
        </HeaderTemplate>
        <ContentTemplate>
            <asp:UpdatePanel ID="up_UpdateContent" runat="server"
                             UpdateMode="Conditional">
                <ContentTemplate>
                    <%# Eval("ContentText")%>
                    <asp:Label ID="lbl_Content" runat="server"
                         Text="<%# DateTime.Now.ToLongTimeString() %>"></asp:Label>
                </ContentTemplate>
            </asp:UpdatePanel>
        </ContentTemplate>
    </asp:Accordion>  
    



    Page_Load() - 准备我们的“虚拟”数据:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (IsPostBack == false)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("ItemID");
            dt.Columns.Add("HeaderText");
            dt.Columns.Add("ContentText");
    
            dt.Rows.Add(new object[] { 123456, "Header 1", "Content A." });
            dt.Rows.Add(new object[] { 654321, "Header 2", "Content B." });
    
            acc_Accordion.DataSource = new System.Data.DataTableReader(dt);
            acc_Accordion.DataBind();
        }
    }
    



    ItemCommand() - 这会捕获 Accordion 内的按钮点击:

    protected void acc_Accordion_ItemCommand(object sender, CommandEventArgs e)
    {
        if (e.CommandName == "UpdatePane")
        {
            AjaxControlToolkit.AccordionContentPanel acp
                = (e as AjaxControlToolkit.AccordionCommandEventArgs).Container;
            UpdatePanel upHeader
                = acc_Accordion.Panes[acp.DisplayIndex].HeaderContainer
                 .Controls.OfType<Control>()
                 .Single(c => c is UpdatePanel) as UpdatePanel;
            LinkButton btn
                = upHeader.ContentTemplateContainer
                 .Controls.OfType<Control>()
                 .Single(b => b is LinkButton) as LinkButton;
            UpdatePanel upContent
                = acc_Accordion.Panes[acp.DisplayIndex].ContentContainer
                 .Controls.OfType<Control>()
                 .Single(c => c is UpdatePanel) as UpdatePanel;
            Label lbl
                = upContent.ContentTemplateContainer
                 .Controls.OfType<Control>()
                 .Single(c => c is Label) as Label;
            lbl.Text = " ID: " + e.CommandArgument
                     + " and Time: " + DateTime.Now.ToLongTimeString();
            //You can use the ID from e.CommandArgument to query the database
            // for data to update your Repeaters with.
            btn.Enabled = false;//Disabling the button for our Header
            // will prevent Asyncronous Postbacks to update the content again.
            //Only disable this if you don't need to update the content
            // when the user clicks to view the pane again.
            upContent.Update();//Set UpdateMode="Conditional".
        }
    }
    



    我知道这看起来很多,但它只是几行代码(在包装和注释之前)。

    【讨论】:

    • 查看我的更新答案,我现在有 1+2 的组合,但这可以改变
    • 我还想指出,您可以使用以下代码通过名称轻松找到您的控件: Label lbl = upContent.ContentTemplateContainer.FindControl("lbl_Content") as Label;我更喜欢尽可能避免使用字符串,但它的执行速度可能比我上面的代码快几纳秒。
    • 嗨,迈克,感谢您提供的代码,我使用上面的代码工作正常,但我有另一个简单的概念展开多个窗格,当我第二次单击时,仅折叠单击的窗格(已经只展开时间) ,如何处理
    【解决方案4】:

    6 Tips for Working with the ASP.NET AJAX Accordion Control 中的提示 4 解释了如何确定所选索引何时更改。从 JavaScript 事件处理程序中,您可以执行任何您想要更新新选择的手风琴窗格内容的操作(调用 Web 服务、使用更新面板等)

    结合另一篇文章解释how to use an update panel to refesh content选择标签页时的简单演示:

        <ajaxToolKit:Accordion ID="accSample" runat="server"
     RequireOpenedPane="false" SelectedIndex="-1">
     <Panes>
      <ajaxToolKit:AccordionPane runat="server">
       <Header>Sample</Header>
       <Content>
     <asp:Button ID="btnSample" runat="server" OnClick="OnShowSample" Style="display: none" />
     <script type="text/javascript">
      Sys.Application.add_load(function (sender, args) {
       if (!args.get_isPartialLoad()) { 
        var accSample = $find('<%= accSample.ClientID %>_AccordionExtender');
        accSample.add_selectedIndexChanged(function (sender, eventArgs) {
         $get('<%= btnSample.ClientID %>').click();
        });
       }
      });
     </script>
     <asp:UpdatePanel ID="upSample" runat="server">
      <ContentTemplate>
       <asp:DataGrid ID="dgSample" runat="server" Visible="false"/>
      </ContentTemplate>
      <Triggers>
       <asp:AsyncPostBackTrigger ControlID="btnSample" />
      </Triggers>
     </asp:UpdatePanel>
       </Content>
      </ajaxToolKit:AccordionPane>
     </Panes>
    </ajaxToolKit:Accordion>
    

    然后在代码隐藏中

    protected void OnShowSample(object sender, EventArgs e)
    {
     dgSample.DataSource = new string[] { "test" };
     dgSample.DataBind();
     dgSample.Visible = true; 
    }
    

    【讨论】:

    • 你测试过这段代码吗?当控件嵌套在可绑定控件中时,您不能像使用 dgSample 那样直接从代码隐藏访问它们,因为可以有很多实例。您必须从绑定控件的特定实例中挖掘它们。请参阅我的答案,您可能需要更新您的答案以检查 accSample 的当前选定索引,以查找和更新 dgSample 的正确实例。使用它开始并查看有效的方法:accSample.Panes[accSample.SelectedIndex]....
    • 如果您不想在中继器中疯狂嵌套,这就是您所需要的。仍然有用,不完全是问什么,但由于这是延迟加载手风琴的第一个谷歌结果(问题的原始版本),我认为这很好。
    • 你说得对,我确实在那儿开枪了。如果您对每个窗格进行硬编码,这就是您所需要的,但如果您想通过绑定到数据来动态创建窗格,则需要调整此解决方案。根据问题的要求,您的答案很好。我喜欢我的,因为如果您将手风琴绑定到数据以动态实例化您的窗格,它会更加健壮。我想我会将您的 javascript 方法与我所拥有的方法结合起来,这样我就可以摆脱标题中的更新面板。谢谢!
    猜你喜欢
    • 2014-10-11
    • 1970-01-01
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-09
    相关资源
    最近更新 更多