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>

17 responses so far ↓
Sonia // January 2, 2008 at 7:37 am |
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
aleem // January 2, 2008 at 7:42 am |
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.
Sonia // January 2, 2008 at 7:54 am |
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.
aleem // January 2, 2008 at 9:31 am |
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.
karthick // February 7, 2008 at 4:40 am |
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#
Leonardo // February 18, 2008 at 11:46 am |
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.
Rich // April 4, 2008 at 2:13 pm |
Would it be possible to put together a zipped Visual Studio 2005 file containing a vb.net solution for this code?
Rich // April 4, 2008 at 2:33 pm |
If users would like to see a working sample in C# you can find it here:
http://blog.lavablast.com/post/2007/12/Hybrid-AccordionTreeView-Sitemap.aspx
Rich // April 4, 2008 at 3:19 pm |
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!
Satish // April 15, 2008 at 5:39 am |
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!
Rana // April 15, 2008 at 11:32 am |
Thanks for the wonderful article.
It solved my problem.
Allah bless you.
Rana
Darmin // May 28, 2008 at 10:17 pm |
Very simple solution
from Chile… thanks a lot !
Baher // June 18, 2008 at 1:29 pm |
Hey guyz i want to write the above source code written in VB in C# , does anyone have a clue how to do it ??
Omego2K // July 16, 2008 at 4:00 pm |
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=”"
Chuck // August 2, 2008 at 6:08 am |
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??
Shalini // October 7, 2008 at 2:15 pm |
Thank you so much Aleem, this is exactly what i was looking for and works perfectly fine for me! Good Job!!!!
The Best of Telerik ASP.NET Ajax Controls « Aleem’s Weblog // February 25, 2009 at 6:03 am |
[...] and we had to reduce postbacks using AJAX. I had used ASP.NET Ajax Control Toolkit before (like here) but I found it limited and you still have to do a lot of work around the toolkit controls to [...]