简体   繁体   中英

lazy loading asp.net Ajax Control Toolkit accordion

I am using the asp.net Ajax Control Toolkit accordion (http://www.asp.net/ajaxlibrary/act_Accordion.ashx) and each accordion pane contains quite a lof information.

All that info is generated in the page but it is not shown because the toolkit gives the non active panes a

 (style="display:none;)

But because the info is in the page, it becomes a very heavy page to load.

I am looking for a way to load the panes on-demand: so only if the user clicks the pane an ajax request is send and the pane is loaded and expanded.

Can this be done with this control or should i choose a different accordion? Any help or suggestions appreciated.

Currently the Accordion is created with two, nested, repeaters. 目前,Accordion是使用两个嵌套的中继器创建的。 The first repeater loops over the categories and creates a panel for each category. The second repeater repeates inside each panel takes the content for one category and creates the content of the panel.

Pleun

I don't have the points to comment and ask you questions. Sorry.
My questions are in regard to how you plan to create and populate the Accordion.

Will you create panes by hand using markup in the IDE or will you bind the Accordion to a DataSource that will dynamically create the panes you need?

Will you have 3 separate DataSources or a different combination of the following:
1.) DataSource to initialize the number of panels and populate only the panel's Header information.
2.) DataSource to populate the Static Content of all panels on first load.
3.) DataSource to populate the Lazy-Loaded Content of a single panel the user clicks to expand.

With your answers I hope to update this answer with a real one. Thanks.


I have some very basic code below as proof of concept. It could be smoother, but I'll leave it up to you to add a "Loading" image using the UpdatingProgress control if you find it necessary.


(Notice the UpdatePanels - you can replace them with callbacks if you want, I just wanted to keep the answer simple)

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



- Prep our "dummy" data: - 准备我们的“虚拟”数据:

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();
    }
}



- This captures button-clicks inside the Accordion: - 它捕获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".
    }
}



I know this looks like a lot, but it's only a few lines of code (before wrapping and commenting).

Tip 4 in 6 Tips for Working with the ASP.NET AJAX Accordion Control explains how to determine when the selected index has changed. From the JavaScript event handler you can do whatever you want to update the content of the newly-selected accordion pane (call a web service, use an update panel, etc.)

Combining this with another article explaining how to use an update panel to refesh content when a tab page is selected for a simple demo:

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

then in code-behind

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

Take a look at the ASPxNavBar control (a part of the free ASPxperience Suite ) from DevExpress . If the ASPxNavBar's EnableCallBacks property is set to true , contents of collapsed groups are not represented on the client side. When a group is expanded for the first time, its content is retrieved from the server and then cached on the client. The next time the group is expanded, its content is taken from the client and no callback to the server is performed.

Review the ASPxNavBar - Callbacks (AJAX) Online Demo for more information.

All I can suggest to you is add linkButtons to your headers and panels to your panes:

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

and in the Accordion1_ItemCommand set the Visible property of corresponding panel.

protected void Accordion1_ItemCommand(object sender, CommandEventArgs e)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM