In this article I am explaining how to build an Accordion Menu using ASP.Net AJAX Accordion control, Sitemap and ASP.Net SiteMapDataSource control. The Accordion menu will also include nested submenus.
To know more about Sitemap and ASP.Net SiteMapDataSource control, please refer the article Using ASP.Net Menu control with example in C# and VB.Net
 
 
Using the ASP.Net AJAX Control Toolkit Accordion Extender Control
1. Drag an ASP.Net AJAX ToolScriptManager on the page.
2. Register the AJAX Control Toolkit Library after adding reference to your project
 
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>
 
 

HTML Markup
The HTML Markup is simple, it contains of an ASP.Net AJAX Control Toolkit Accordion Extender Control with a HyperLink in HeaderTemplate and a Repeater control placed inside ContentTemplate and a SiteMapDataSource control.
The Hyperlink inside the HeaderTemplate is populated with the Title and URL attributes of the first level nodes of the Sitemap while the HyperLink controls inside the Repeater control populated with Title and URL attributes of the child or sub-menu items of the Sitemap.
<cc1:ToolkitScriptManager runat="server">
</cc1:ToolkitScriptManager>
<cc1:Accordion ID="AccordionMenu" runat="server" OnItemDataBound="OnItemDataBound" Width = "300"
    HeaderCssClass="header" HeaderSelectedCssClass="header_selected" ContentCssClass = "content">
    <HeaderTemplate>
        <asp:HyperLink ID="lnkMenu" NavigateUrl='<%# Eval("Url") %>' Text='<%# Eval("Title") %>' runat="server" />
    </HeaderTemplate>
    <ContentTemplate>
        <table>
            <asp:Repeater ID="rptMenu" runat="server">
                <ItemTemplate>
                    <tr>
                        <td>
                            <asp:HyperLink ID="HyperLink1" NavigateUrl='<%# Eval("Url") %>' Text='<%# Eval("Title") %>'
                                runat="server" />
                        </td>
                    </tr>
                </ItemTemplate>
            </asp:Repeater>
        </table>
    </ContentTemplate>
</cc1:Accordion>
<asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" ShowStartingNode="false" />
 
 
Adding the Sitemap XML and understanding its use
Sitemap is nothing but a map of your site, it is an XML files which has all the Pages and the Child Pages present in the site. Whenever a new page has to be added to your site, you simply need to add its node in the sitemap XML file and the ASP.Net Menu control will automatically grab and display it.
Sitemap can be added using Add New Item Dialog of Visual Studio as shown below.
Populate ASP.Net AJAX Accordion Menu with Submenu using Sitemap
 
Once the file is added you need to structure it based on the Level 1 Pages and the Child Pages.
Note: You can have as many child levels as you want, here I am using 2 Level Menu structure
 
Below is the sitemap I am using for this article, it has the following page structure.
<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
 <siteMapNode url="" title="Home" description="">
    <siteMapNode url="Home.aspx" title="Home" description="Home Page" />
    <siteMapNode url="javascript:;" title="Services" description="Services Page">
      <siteMapNode url ="Consulting.aspx" title="Consulting" description="Consulting Page"></siteMapNode>
      <siteMapNode url ="Outsourcing.aspx" title="Outsourcing" description="Outsourcing Page"></siteMapNode>
    </siteMapNode>
    <siteMapNode url="About.aspx" title="About" description="About Us Page" />
    <siteMapNode url="Contact.aspx" title="Contact" description="Contact Us Page" />
 </siteMapNode>
</siteMap>
 
Home => Home.aspx
Services
            Consulting => Consulting.aspx
            Outsourcing => Outsourcing.aspx
About => About.aspx
Contact => Contact.aspx
 
 
Namespaces
You will need to import the following namespaces.
C#
using AjaxControlToolkit;
 
VB.Net
Imports AjaxControlToolkit
 
 
Populating the ASP.Net AJAX Accordion control from Sitemap using SiteMapDataSource control
The data from the SiteMapDataSource is selected in a form of DataView and assigned to the ASP.Net AJAX Accordion control DataSource.
Then inside the ItemDataBound event of the AJAX Accordion control, the ASP.Net Repeater control placed inside in it is found and child nodes of the SiteMapNode are assigned to it, which in turn populates the child or sub-menu items of the Accordion Menu.
C#
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        AccordionMenu.DataSource = (SiteMapDataSource1.GetView("") as SiteMapDataSourceView).Select(DataSourceSelectArguments.Empty);
        AccordionMenu.DataBind();
    }
}
 
protected void OnItemDataBound(object sender, AccordionItemEventArgs e)
{
    if (e.ItemType == AccordionItemType.Header)
    {
        string menuText = (e.AccordionItem.FindControl("lnkMenu") as HyperLink).Text;
        if (menuText == SiteMap.CurrentNode.Title || menuText == SiteMap.CurrentNode.ParentNode.Title)
        {
            AccordionMenu.SelectedIndex = e.ItemIndex;
        }
    }
    if (e.ItemType == AccordionItemType.Content)
    {
        AccordionContentPanel cPanel = e.AccordionItem;
        Repeater rptMenu = (Repeater)cPanel.FindControl("rptMenu");
        rptMenu.DataSource = (e.AccordionItem.DataItem as SiteMapNode).ChildNodes;
        rptMenu.DataBind();
    }
}
 
VB.Net
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
    If Not IsPostBack Then
        AccordionMenu.DataSource = TryCast(SiteMapDataSource1.GetView(""), SiteMapDataSourceView).[Select](DataSourceSelectArguments.Empty)
        AccordionMenu.DataBind()
    End If
End Sub
 
Protected Sub OnItemDataBound(sender As Object, e As AccordionItemEventArgs)
    If e.ItemType = AccordionItemType.Header Then
        Dim menuText As String = TryCast(e.AccordionItem.FindControl("lnkMenu"), HyperLink).Text
        If menuText = SiteMap.CurrentNode.Title OrElse menuText = SiteMap.CurrentNode.ParentNode.Title Then
            AccordionMenu.SelectedIndex = e.ItemIndex
        End If
    End If
    If e.ItemType = AccordionItemType.Content Then
        Dim cPanel As AccordionContentPanel = e.AccordionItem
        Dim rptMenu As Repeater = DirectCast(cPanel.FindControl("rptMenu"), Repeater)
        rptMenu.DataSource = TryCast(e.AccordionItem.DataItem, SiteMapNode).ChildNodes
        rptMenu.DataBind()
    End If
End Sub
 
Populate ASP.Net AJAX Accordion Menu with Submenu using Sitemap
 
Demo
 
Downloads