Using ASP.NET AJAX Accordion Control with Sitemap

ASP.NET AJAX accordion control is a wonderful control made of collapsible panels with an animation effect. Accordion control is mostly used for long content pages with various collapsible sections. The control can also be used as a site menu, collapsible panels gives a very good effect when accordion is used as a site menu.

In ASP.NET any menu control needs to be attached to the web.sitemap file to display the site navigation. Although accordion control does not provide this facility by default as the ASP.NET TreeView control (Accordion cannot be directly binded to SiteMapDataSource object as TreeView) but it is fairly simple to achieve that.

You need to drop a SiteMapDataSource object on the page and then bind the accordion control with the SiteMapNodeCollection instead of SiteMapDataSource. Get the SiteMapNodeCollection from SiteMapDataSource as follows and bind to the accordion control.

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
Dim siteMapView As SiteMapDataSourceView = CType(SiteMapDataSource1.GetView(String.Empty), SiteMapDataSourceView)
Dim nodes As SiteMapNodeCollection = CType(siteMapView.Select(DataSourceSelectArguments.Empty), SiteMapNodeCollection)
Accordion1.DataSource = SiteMapNodeCollection
Accordion1.DataBind()
End If
End Sub

In the aspx page add a repeater control in the <contenttemplate> of the accordion control to show the child items in the collapsible panel. The header of the accordion will show the first level nodes from the sitemap and the collapsible panel will show the child nodes of the header item.

<cc1:Accordion ID=”Accordion1″ runat=”server” SelectedIndex=”0″ FadeTransitions=”false”
FramesPerSecond=”40″ TransitionDuration=”250″ AutoSize=”None” RequireOpenedPane=”true”
SuppressHeaderPostbacks=”true” HeaderCssClass=”AccordionHeaderCssClass”>
<HeaderTemplate>
<a class=”AccordionSideBarLink” href='<%# Eval(“url”) %>’>
<%# Eval(“title”) %>
</a>
</HeaderTemplate>
<ContentTemplate>
<table>
<asp:Repeater ID=”Repeater1″ runat=”server”>
<ItemTemplate>
<tr>
<td id=”AccordionSideBarItem”>
<a class=”AccordionSideBarItemLink” href=”<%# CType(Container.DataItem, System.Web.SiteMapNode).Url %>”>
<%#CType(Container.DataItem, System.Web.SiteMapNode).Title%>
</a>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
</ContentTemplate>
</cc1:Accordion>

In order to bind the repeater control with the child nodes, add the following code in the Accordion DataBound control.

Protected Sub Accordion1_DataBound(ByVal sender As Object, ByVal e As AjaxControlToolkit.AccordionItemEventArgs) Handles Accordion1.ItemDataBound
If CType(e, AjaxControlToolkit.AccordionItemEventArgs).ItemType = AjaxControlToolkit.AccordionItemType.Content Then
Dim cPanel As AjaxControlToolkit.AccordionContentPanel = e.AccordionItem
Dim rptr As System.Web.UI.WebControls.Repeater = CType(cPanel.Controls(1), System.Web.UI.WebControls.Repeater)

Dim sNode As System.Web.SiteMapNode = CType(CType(e, AjaxControlToolkit.AccordionItemEventArgs).AccordionItem.DataItem, System.Web.SiteMapNode)
Dim childNodes As System.Web.SiteMapNodeCollection = sNode.ChildNodes
If Not childNodes Is Nothing AndAlso childNodes.Count > 0 Then
rptr.DataSourceID = Nothing
rptr.DataSource = childNodes
rptr.DataBind()
End If
End If
End Sub

and this is how my web.sitemap is arranged.

<?xml version=”1.0″ encoding=”utf-8″ ?>
<siteMap xmlns=”
http://schemas.microsoft.com/AspNet/SiteMap-File-1.0″ enableLocalization=”true”>

<siteMapNode url=”~/Login/Main.aspx” title=”$resources: SiteMap, ServicesHome” description=”” ImageUrl=”~/App_Themes/Standard/Images/ServicesHome_Small.gif” >

.
.
.
<siteMapNode url=”” title=”$resources: SiteMap, Licenses” description=”” ImageUrl=”~/App_Themes/Standard/Images/Licenses_Small.gif” EntityName=”LicenseBox” >
<siteMapNode url=”javascript:openWindow(‘../License/License.aspx?mode=new’,950,600,’License’)” title=”$resources: SiteMap, NewLicense” description=”” EntityName=”License” AccessType=”new”/>
<siteMapNode url=”javascript:openWindow(‘../LicenseRenewal/LicenseRenewal.aspx?mode=new’,950,600,’LicenseRenewal’)” title=”$resources: SiteMap, RenewLicense” description=”” EntityName=”LicenseRenewal” AccessType=”new”/>
<siteMapNode url=”javascript:openWindow(‘../LicenseCancel/LicenseCancel.aspx’,950,600,’LicenseCancel’)” title=”$resources: SiteMap, CancelLicense” description=”” EntityName=”LicenseCancel” AccessType=”new”/>
<siteMapNode url=”javascript:openWindow(‘../LicenseAmmendment/LicenseAmmendment.aspx’,950,600,’LicenseAmmendment’)” title=”$resources: SiteMap, AmmendLicense” description=”” EntityName=”LicenseAmmendment” AccessType=”new”/>
<siteMapNode url=”~/License/LicenseListing.aspx” title=”$resources: SiteMap, ExistingLicenses” description=”” EntityName=”LicenseListing”/>
<siteMapNode url=”javascript:openWindow(‘../Documents/Licensing Department Conditions.pdf’,950,600,’LicenseHelp’)” title=”$resources: SiteMap, LicenseHelp” description=”” EntityName=”Help” />
</siteMapNode>
.
.
.
</siteMapNode>
</siteMap>

About these ads

26 thoughts on “Using ASP.NET AJAX Accordion Control with Sitemap

  1. Hi, It looks like a nice article however I have copy your sample code and I got several different errors. Your code is incomplete and therefore does not work. When you write an article, please make sure the code you post with is all there and you have tested that. Thanks

  2. Hi Sonia,

    Can you please let me know what problem you are having so I can rectify if there is any problem with the code. I cannot paste the entire project, I have just posted the portions of the code which I believe would be enough for understanding what is being done here.

    Let me know if you need a sample project or full code.

  3. Hi Aleem, thanks for your fast response. I have converted the code into C#: Here is the code:

    protected void Page_Load(object sender, EventArgs e)
    {
    if (!IsPostBack)
    {
    SiteMapDataSourceView siteMapView = (SiteMapDataSourceView)SiteMapDataSource1.GetView(string.Empty);
    SiteMapNodeCollection nodes = ((SiteMapNodeCollection) (siteMapView.Select(DataSourceSelectArguments.Empty)));
    Accordion1.DataSource = nodes;
    Accordion1.DataBind();
    }
    }

    protected void Accordion1_DataBound(object sender, AjaxControlToolkit.AccordionItemEventArgs e)
    {
    if (((AjaxControlToolkit.AccordionItemEventArgs)e).ItemType == AjaxControlToolkit.AccordionItemType.Content) {
    AjaxControlToolkit.AccordionContentPanel cPanel = e.AccordionItem;
    System.Web.UI.WebControls.Repeater rptr = (System.Web.UI.WebControls.Repeater)cPanel.Controls(1);
    System.Web.SiteMapNode sNode = (System.Web.SiteMapNode)((AjaxControlToolkit.AccordionItemEventArgs)e).AccordionItem.DataItem;
    System.Web.SiteMapNodeCollection childNodes = sNode.ChildNodes;
    if ((childNodes != null) && childNodes.Count > 0)
    {
    rptr.DataSourceID = null;
    rptr.DataSource = childNodes;
    rptr.DataBind();
    }
    }
    }

    Error: The name ‘SiteMapDataSource1′ does not exist in the current context

    If I add a sitemapdatasource tag in the html then i will start getting other errors such as System.Configuration.ConfigurationErrorsException: Resource key cannot be empty.

    Appreciated that you replied so fast thanks. As I said the article looks nice :). By the way, you may want to take a look at this control: http://www.metabuilders.com/Tools/MultiViewBar.aspx Another interesting menu.

  4. It is sort of given that you will need a SiteMapDataSource and I have also mentioned in the post that you need to drop one on the page.

    The error “Resource Key cannot be empty” seems to be in your web.sitemap file. If you are using my sitemap file it may not work as it is using resource keys which you will not have, it was supposed to help you understand the arrangements sitemap file only.

    Create a simple web.sitemap file only following the hierarchy provided in the sample and then check.

    I hope it will work.

  5. hi aleem,
    am new to asp.net
    i need to know whether we can use gridview inside accordion?
    my problem is..accordion is connected with one datasource..am displaying som values in header template with that datasource..
    in content template i kept one gridview…i need to connect sqldatasource to that gridview..am cant able to connect.Gridview is not displaying?
    do you knw any other method to solve this?

    kindly send me some sample code..using C#

  6. Hi Aleem,

    Thanks for the article.
    I was doing something similar except for the child using OnItemDataBound. It works fine ! My only concern is with items that has been shown even for user with no permission.

    The child nodes which the user has no permission to see are been shown accordingly (Repeater inside), but for the nodes displayed on HeaderTemplate, all nodes are appearing which is very weird.

    Any idea what must be causing it?

    Thanks.

  7. Would it be possible to put together a zipped Visual Studio 2005 file containing a vb.net solution for this code?

  8. When binding to the accordion control you have:

    Accordion1.DataSource = SiteMapNodeCollection

    Shouldn’t this be

    Accordion1.DataSource = nodes

    I’m just wetting my feet with this stuff so forgive me if I’ve assumed incorrectly!

  9. Hi Aleem,

    This is nice article, i also worked in vertscape bangalore, i went through the application it was very good, but it had this control not working properly on IE7 or 6 right ?
    I just wanted to know how did you fixed it? what was the problem? If you can explain us it would be very help full for us!

  10. For some reason it’s not working for me. I get the links for the root nodes that should be able to be clicked to expand the child nodes however that doesn’t happen, they just replace the page and have an href=””

  11. Just a note for C# developers, don’t forget to add the event:
    MyAccordion.ItemDataBound += new EventHandler(MyAccordion_ItemDataBound);

    ..if you want it to run the ItemDataBound event.

    Aleem, how do you get the selected index of he root node when a user clicks a childnode??

  12. Pingback: The Best of Telerik ASP.NET Ajax Controls « Aleem’s Weblog

  13. It works, but it does not show the currently visible page. This could be done in the ItemDataBound event of the repeater.

    Here’s a C# sample:

    protected void AccordionRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
    HyperLink hl = (HyperLink)e.Item.FindControl("hlSubMenuItem");
    AccordionPane ap = (AccordionPane)e.Item.Parent.Parent.Parent;
    Accordion ac = (Accordion)ap.Parent;
    SiteMapNode sn = (SiteMapNode)e.Item.DataItem;

    hl.Text = sn.Title;
    hl.NavigateUrl = sn.Url;
    if (Request.Url.AbsoluteUri.ToLower().Contains(sn.Url.ToLower()))
    {
    hl.CssClass="SelectedItemClass";
    ac.SelectedIndex = ac.Panes.IndexOf(ap);
    }
    }

  14. Hello Aleem,

    I try your example so to bind an Accordion Control with Sitemap..
    but I get the errors:

    SiteMapNodeConnection is a type and cannot be used as an expression

    Name ‘SiteMapDataSource’ is not declared

    Can you please help me out with that..

    regards

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s