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>