TreeView control is Microsoft's solution for hierarchical web site navigation, but unfortunately, it's not great for public web sites. As a result, we avoid using the ASP.NET
TreeView for public web sites. It relies on excessive table layouts, requires a form
runat=server, and also needs a large viewstate. Each of these issues can be addressed, but in this article, I present a cleaner, more elegant solution for your hierarchical site navigation.
Using the code
The web.sitemap is a great place to keep the site map information for your site. This solution assumes that you use web.sitemap, but could easily be adapted for other site map providers.
<siteMapNode url="default.aspx" title="Home" description="Home Page">
<siteMapNode url="/about/default.aspx" title="About" >
<siteMapNode url="/about/history/default.aspx" title="History" >
<siteMapNode url ="/about/history/earlyyears.aspx" title ="The Early Years" />
<siteMapNode url ="/about/history/modernday.aspx" title ="Modern Day" />
<siteMapNode url="/about/management/default.aspx" title="Management" />
<siteMapNode url="/about/mission/default.aspx" title="Mission Statement" />
<siteMapNode url="/about/locations/default.aspx" title="Locations" />
<siteMapNode url="/products/default.aspx" title="Product Line" >
<siteMapNode url ="/products/widgetX2000.aspx" title ="Widget 2000" />
<siteMapNode url ="/products/widgetX2005.aspx" title ="Widget 2005" />
<siteMapNode url ="/products/widgetX5000.aspx" title ="Widget 5000 *New*" />
To output your hierarchical navigation, I recommend the use of
The code that binds to your web.sitemap is very basic, it simply relies on nested
Repeaters to bind to the XML.
<asp:XmlDataSource runat="server" DataFile="~/web.sitemap"
id="dsXMLSitemap" XPath="/siteMap/siteMapNode/siteMapNode[@title='About']" />
<ul id="ulLeftMenu" class="mktree">
<asp:repeater DataSourceID="dsXMLSitemap" ID="dlXMLSitemap" Runat="server">
<li><a href="<%# XPath("@url")%>">
Optimize with output cache
In order to optimize this code, I recommend adding output caching to your navigation user control. While the work to render out the navigation is not that significant, it still requires I/O and processing. Also, if your web.sitemap file is large, loading that into memory for every hit could take significant resources.
Minor cleanup needed
Looking at the above code, you may notice that the header template and footer template always output the opening and closing
ul tags. As a result, even if no nodes are found, you'll have an empty set of tags. The code to fix this is shown below:
public void cleanUpHeader(object source, EventArgs args)
Repeater rpt = (Repeater)source;
if (rpt.Items.Count == 0)
rpt.Visible = false;
Now, simply add an event handler on your
<asp:repeater ID="Repeater1" DataSource='<%# XPathSelect("siteMapNode") %>'
- 1.0 - Initial article released.
Seth Berger is a Technology Director at WHITTMANHART Interactive. At WHITTMANHART he develops and manages large .NET projects for some of the world's most successful companies. He is skilled in a large number of languages and development environments but his primary focus is on ASP.NET development, and has worked on it since it was in beta. He previously co-founded Estco Medical, a web development and software company focused on the life-science industry.