Implementing Incremental Navigation with ASP.NETBy Andrew Wrigley
Traditionally, website navigation has been focused on minimizing the number of clicks required to open a given page. However, this goal has nothing to do with the real purpose of navigation, which is to make finding information easy, consistent, and transparent to the user. Also, as websites get bigger, traditional navigation controls such as drop-down menus or tree views become impractical. Faster Internet connections and larger screen sizes now allow developers to experiment with new styles of navigation.
This article shows how to implement incremental navigation, which is a style of navigation where users find information by clicking through a series of lightweight pages, with each click resulting in a small, but highly visible change to the navigation user interface. It differs from traditional drop-down menu navigation in that incremental navigation limits the amount of new choices available to just the next level in the sitemap hierarchy.
I've created a customizable framework for implementing this sort of navigation scheme named Theseus, which you can download from the end of this article. Underneath the
covers, Theseus uses ASP.NET's
SiteMap class and the configured sitemap provider
to implement the incremental navigation. This article starts with an overview of incremental navigation and then goes on to examine how to use Theseus to implement
such a navigation scheme in your website. Read on to learn more!
The Benefits of Incremental Navigation
Modern websites increasingly use an incremental navigation paradigm: users find information by clicking through a series of lightweight pages, with each click resulting in minimal but highly visible changes to the navigation controls. Incremental navigation differs from traditional drop-down menu navigation in that it limits the amount of new choices available to just the next level in the hierarchy of information. It also highlights the "current branch" (or "breadcrumb") in the hierarchy, where the current branch is the path that the user has followed to reach the current node. Highlighting the current branch shows users how they got to where they are and how they can retrace their steps. This is how our brains work, so users find this kind of navigation intuitive. It also minimizes the markup that gets rendered with each request.
On the contrary, drop-down menus force users to think in terms of hierarchies of which they may have no previous knowledge. They also offer all available choices at all times thereby maximizing the rendered markup, but offer little or no visual indication of the current branch. As a result, a user's sense of frustration and confusion increases exponentially with the number of levels in the hierarchy of information. Now why would you do that to your users?
A Working Example of Incremental Navigation
To see incremental navigation in action, take a look at the The Encephalitis Society website. This site consists of hundreds of pages nested in a hierarchy that is up to five levels deep. Visitors to this site vary from people affected by Encephalitis - which can cause severe brain injury - to medical professionals. As a result, a consistent navigation is central to the usability of this website.
The navigation on the Encephalitis Society website has three main elements:
- The site tabs,
- The section menu, and
- The side menu
The Structure of the Navigation System
The site tabs are the series of tabs along the top of the page - Home, Information, The Society, and so forth. Selecting a site tab takes the user to the landing page for that tab. It also highlights the site tab and displays the subelements in the section menu. The screen shot below shows the navigation UI after the user has selected the Information tab. The background and foreground colors of the site tabs makes it clear that the Information tab has been selected.
A Tab Selected From the Site Tabs
The user can drill down further into the site by clicking on one of the links in the section menu - The Illness, Recovery and Rehabilitation, and so on. Clicking on one of these section menu options takes the user to a new page and highlights the selected section menu option by bolding its text (see the screen shot below). It also loads any subelements of the section menu into a side menu.
An Item Selected from the Section Menu
The side menu displays all remaining sitemap nodes for the selected section menu option. In the following screen shot the user has expanded the What is Encephalitis option from the side menu and clicked on the Causes of Encephalitis entry. This displays a page that details the causes of the encephalitis. Note that the navigational user interface clearly indicates the current branch to the user. Through the use of colors and bolded text it is apparent that the user is viewing the Causes of Encephalitis page, which is a subelement of What is Encephalitis, which is a subelement of The Illness, which is under the Information section.
A Page Selected from the Side Menu
An incremental navigation system obviates the need for a breadcrumb control (the ASP.NET SiteMapPath control) because it is immediately clear how the user arrived at any page: the current branch is highlighted in an obvious way. The user is not forced to think hierarchically and so navigating the site is intuitive and easy.
Before continuing on, take a moment to visit The Encephalitis Society website to get a good feel of how the navigation system
works. While it may not be apparent, the navigation system on The Encephalitis Society website uses ASP.NET's sitemap system and navigational Web controls. The navigational
sections of the site are defined in the
Web.sitemap file. The site tabs and section menu are implemented using the ASP.NET Menu control; the side menu is
implemented via the ASP.NET TreeView control.
Building an Incremental Navigation Framework
When designing the incremental navigation for The Encephalitis Society website I wanted to do so using a componentized, reusable model so that I (or others) could plug such a navigation system into other ASP.NET websites. I ended up creating a framework (written in C#) that I named Theseus after the mythological slayer of the Minotaur in the Labyrinth. The Theseus framework and a demo web application are available for download at the end of this article.
Theseus is packaged into five files. The names are pretty self explanatory:
- Two User Controls (
.ascxfiles) provide the UI and plug into your master page(s):
- Two classes contain the code that powers Theseus:
- Finally, there is a class that provides the structure to ensure that the Theseus boilerplate code is available to all pages in your website:
Web.sitemapfile; however, you could plug in an alternate sitemap provider and use Theseus the same. What's more, the demo application uses the CSS Friendly Menu and TreeView control adapters and uses CSS for styling. The CSS Friendly adapters alter the markup emitted by ASP.NET's TreeView and Menu controls to use
<ul>'s rather than
<table>s, and focuses on defining style information through CSS classes rather than through the HTML elements'
styleattributes. For more on the CSS Friendly Control Adapters, see http://www.asp.net/CssAdapters.
Nuts and Bolts
The site tabs and the section menu are both implemented using ASP.NET Menu controls and are packaged into the
TopMenus.ascxfile. The side menu is implemented using an ASP.NET TreeView control and is packaged into the
SideMenu.ascxfile. The Menu controls and the TreeView control are declaratively bound to their own SiteMapDataSource controls.
Take a look at the pertinent markup for SideMenu.ascx:
The markup for
TopMenus.ascx is even simpler. You can view it by downloading the demo available at the end of this article.
SideMenu.ascx code behind file, shown below, is fairly straightforward, too. Note that the code to populate the side menu is contained within the Theseus
SideMenu.ascx User Control merely hands over the TreeView control to the Theseus framework via a call to the
LoadSideMenu method then adds the nodes to show in the side menu. The
SetNodeSideMenu method, called from the
handler, expands the necessary nodes in the TreeView. We'll examine the inner workings of both these method later on in this article.
In addition to populating and expanding the side menu as needed, the
Page_Load event handler also displays the title of the section menu node in the
lblSideMenuHeader Label control. This Label control is not part of the Theseus framework, but is rather an example of how to add additional, customized
content to the
SideMenu.ascx User Controls to conform to any specific requirements for the site.
A Custom Base Class for All Pages:
The Theseus framework is powered by the class
TheseusClass. This class contains methods like
LoadSideMenu, and is used by the
SideMenu.ascxUser Controls to populate the appropriate content into their navigation user interface elements. Since this class is used by every page in the website, I created a custom base page class named
TheseusPagethat has a property named
Theseusthat returns an instance of the
TheseusClassclass. Consequently, all ASP.NET web pages that use the Theseus framework need to inherit from this custom base class.
If you create your ASP.NET pages where the markup and code is in the same file then you can make
TheseusPage the base class to all your pages by using the
pageBaseType attribute of the
<pages> section in
If you have your ASP.NET pages' markup and code sections separated into two files then you will need to go through each code behind file and changing the base class that
your pages inherit from
Wingspan.Web.Core.TheseusPage (or whatever you call your custom base class):
For more information on using a custom base page class and its benefits, refer to Using a Custom Base Class for your ASP.NET Pages' Code-Behind Classes.
The Engine That Powers Theseus:
The Theseus framework is powered by
TheseusClass, which has two core tasks:
- Determining what items in the sitemap need to be displayed in the top menus and side menu given the page being visited, and
- Determining the current branch so that we know what items in the navigation user interface need to be highlighted.
SiteMapclass is part of the ASP.NET framework and provides an "in memory representation of the navigation structure for a site, which is provided by one or more site map providers."
The most important property of the
SiteMap class is
CurrentNode, which represents the
object in the sitemap structure that corresponds to the page being currently requested.
If the page being requested is not represented by a node in
null. In this case, Theseus goes into
its "inactive" state and shows only the Site Menu with no tabs highlighted.
The other important
SiteMap property is
RootNode, which returns the
SiteMapNode that is the root of the sitemap hierarchy. The
RootNode properties are used to determine the current branch, as the current branch is, by definition, the path between the
current node and the root.
Theseus needs to calculate the current branch as a
SiteMapNodeobjects. It would have been nice if Microsoft had implemented a property such as
SiteMap.CurrentBranch, but they didn't. Fortunately, this
Listcan be computed with only a few lines of code. In addition to computing the current branch
List, there are a number of other sitemap-related tasks that Theseus needs to perform that are not built into the
SiteMapclass. These methods and properties are grouped into a class named
SiteMapExtensions; this class is used from the
TheseusClassclass, which includes a member variable named
The code in
SiteMapExtensions class is pretty straight forward and well documented. There is the
CurrentBranch property, which returns the
SiteMapNodes that makes up the current branch; a
CurrentNodeLevel property, which returns the level of the current node in the sitemap hierarchy;
and a handful of methods.
TheseusClass In Detail
To get a better understanding of how Theseus works, I'd like to explore the code in
TheseusClassthat relates to the TreeView control (the Side Menu) in detail. Recall that the
SideMenu.ascxUser Control is responsible for displaying the side menu using a TreeView control. Its
Page_Loadevent handler populates the TreeView with the appropriate nodes based on the requested page by calling the
LoadSideMenumethod, passing in both the SiteMapDataSource (
dsMenu3) and the TreeView (
tvMenu3) controls defined in the User Control's markup portion:
LoadSideMenu method starts by getting a reference to the node in the Section Menu that has been selected and storing it in a variable named
(Recall that the Side Menu displays the descendant nodes of the
SiteMapNode selected from the Section Menu.) This selected Section Menu
retrieved by calling the
CurrentBranchNode method, passing in the
SectionMenuLevel variable. This
SectionMenuLevel variable is an integer value that indicates what level of the sitemap hierarchy was rendered in the Section Menu. In our sample, this value is
set to 2, but can be customized via the
Now that we have the selected Section Menu node we check to see if it is
null. It would be
null if the selected Site Tab is a leaf node. For example,
if the page being requested was the Home Page then
node2 would be
node2 is not
null, then we need to ensure that
the Side Menu TreeView control (the
tv parameter) is made visible, that it is expanded to the correct depth, and that it shows the descendant nodes
Note that we set the
dsMenu3 SiteMapDataSource control's
StartingNodeUrl property to the URL of the selected Section Menu node (
Because the SiteMapDataSource has had its
ShowStartingNode property set to false in the User Control markup only the children nodes of
node2 will be returned.
ExpandDepth property indicates how many levels of TreeView nodes are expanded, by default. This value is determined by the level of the current
node in the sitemap hierarchy, which is available via the
CurrentNodeLevel property in the
SiteMapExtensions class. That's all we need to do to
load the Side Menu. However, there still remains one important part in rendering the Side Menu: we need to highlight the appropriate nodes in the TreeView based on the
Highlighting the appropriate nodes in the TreeView can only happen once the data has been bound to the control. The TreeView's
DataBound event is raised after
the data has been bound to the TreeView. Therefore, it makes sense to create an event handler for the DataBound event and to put the logic there for selecting the appropriate
TreeView nodes. This event handler is defined in the
SideMenu.ascx User Control and simply calls the TheseusClass's
SetNodeSideMenu method, passing
in the TreeView control.
SetNodeSideMenu method starts by collapsing all of the TreeView nodes. This guarantees that only the nodes on the current branch will be expanded, which
is what we want. Next, the method checks to see if there is a selected node in the TreeView; if so, that node is expanded. If there is no selected node then the TreeNode that
SiteMap.CurrentNode is selected. Finally, the selected node's parent is expanded to guarantee that the selected node will be visible on the
SetNodeSideMenu method follows:
The most common scenario is that there was no selected node. In this case the
SetSelectedTreeNode method gets called. This
is in charge of selecting the TreeNode that represents the
SiteMapNode object. The only complication with this code is to map
SiteMap.CurrentNode to one of the TreeNodes. To do that, I use the TreeView's
FindNode method, and the whole problem is reduced to building the
ValuePath to the current node:
The eagle eyed reader may have noticed that this code only selects the current node. How do I make the other nodes along the current branch aware that they should display in bold?
The answer is that I don't need to do anything. Using the CSS Friendly Adapters causes the nodes along the current branch to all have a CSS class of
AspNet-TreeView-ChildSelected. Therefore, I can set these display-related settings in the CSS definition without having to write any C# code. For more on this
look at the CSS in the
ValuePath is really simple because we can build it from the
CurrentBranch property of the
SiteMapExtender object. I have packaged the code that does this into the
The code for
CurrentNodeValuePath is pretty simple, you just need to be careful with the
startFromLevel parameter to make sure you calculate the
ValuePath from the right place.
All we need now is the code for the
ExpandSideMenu method. This method starts from the
CurrentNode and works back up the tree using the
Parent property, expanding the parent at each step.
Many users (and clients) hate drop down menus. Users hate thinking hierarchically, which is what drop down menus force them to do.
From a technological perspective, drop down menus are a hangover from the days of small screens and dial up Internet connections and if you, as the developer, are not yet convinced of the benefits of incremental navigation, just think of a website where the information is nested in a hierarchy of pages that is five levels deep. Drop-down menus, anyone? No, I didn't think so.
The Theseus framework is just as easy to use in your websites as a Menu control. Its User Interface is highly customizable and it renders standards compliant markup that is much more optimized than traditional drop down menus. Your users no longer need a ball of string to kill the Minotaur.
SiteMapclass technical docs
A Word About The Encephalitis Society
I decided to write this article in March 2009 after watching Red Nose Day coverage on the BBC. Red Nose Day is a UK thing, where you are encouraged to do something fun for charity.
My first ever client was Elaine Dowell, chairperson of the Encephalitis Society. Encephalitis is an inflammation of the brain, caused by an infection. It can cause severe acquired brain injury, even death. Many people recover pretty much completely, but it can also lead to terrible long term consequences and suffering for the people affected, as well as for their family and caretakers. When Elaine's son got Encephalitis, a rare but all too often devastating syndrome, she decided to do something. Ten years later, she is still doing just that.
The story that best sums Elaine up is this one: I was in the Society offices one day discussing changes to the website. A group of new regional reps turned up for a meeting with the regional coordinator whilst Elaine and I went to war over a pixel here, a hue there. As the reps were leaving one of them, a middle aged lady, hung back. When the others had left, she asked: "Is Elaine Dowell here?" The receptionist brought her over to meet Elaine. "You are my family's hero," said the new rep. "We would never have survived without you."
Hopefully, you won't ever need a hero to save your family. But if this article helped you in your daily work then go do the right thing - visit The Encephalitis Society website and click the Make a Donation button. You will feel really good and your nose will turn red. The more you donate, the redder it will go. If you don't believe me, just click the Make a Donation button and see for yourself. Make sure you have a mirror handy.