ASP.NET 2.0 #3: Navigation

Let's say that you have to, as I did once, develop a menu like the one illustrated here:

 

 

As users make selections from the menu, sub-menu items are revealed, while the selections that the user has already made are tracked at the top of the menu.

Besides the requirements for how the menu is to behave for users, of course one would like the menu to have any number of levels. One would also like to be able to add items to any level without having to write any code in doing so.

 

When I developed this menu for an ASP.NET 1.1 version of my application, these are the steps that were necessary. First, I created an XML schema to describe the structure of a document to describe the menu. Second, I used the .NET xsd tool to generate a .NET class from the schema that could serialize itself to and from XML documents conforming to the schema. Third, I created an XML document in conformity with the schema to describe the structure of the menu. Fourth, I used the Configuration Application Block provided by Microsoft’s Prescriptive Architecture Group to incorporate the XML document describing the menu into the Web.config file of the application, and to automatically read the contents of that document into an instance of the .NET class I had generated from the schema. Fifth, I had the menu page’s Load event handler call a routine that emitted the HTML depicting the menu from the content of the instance of the .NET class, along with some JScript that would modify the HTML and thereby update the appearance of the menu as the user navigated through it. Including the class generated using the xsd tool, that took two hundred lines of code to accomplish.

 

Let’s see what is involved in creating the same arbitrarily-complex, extensible menu using ASP.NET 2.0. We have four new facilities at our disposal.

The first of these facilities is the Site Map. Site maps are XML files describing the arrangement of the pages in a Web site.

The second facility we can use in constructing our menu is the SiteMapDataSource. The SiteMapDataSource is a control that can be used to bind the content of a site map to the display properties of other controls.

The third facility is the Menu control. The menu control is a control for displaying a menu on a Web form, and it can be bound to a SiteMapDataSource so as to build the menu automatically from the content of the site map.

The fourth facility ASP.NET 2.0 provides us for building our menu is the SiteMapPathControl. The SiteMapPath control is a control for showing users where they are located among the pages of an application, and for providing them with links to jump to other locations.

Using those tools, here is what it takes to get our menu working:

Web.SiteMap file:

<?xml version="1.0" encoding="utf-8" ?>
<siteMap>
<siteMapNode url="./Main.aspx" title="Main Menu">
<siteMapNode url="./Contracts/Contracts.aspx" title="Contracts" >
<siteMapNode url="./Contracts/DocumentManagement/DocumentManagement.aspx" title="Document Management" >
<siteMapNode url="./Contracts/DocumentManagement/Reception.aspx" title="Receive" />
<siteMapNode url="./Contracts/DocumentManagement/Assignment.aspx" title="Issue" />
<siteMapNode url="./Contracts/DocumentManagement/Status.aspx" title="Update Status" />
</siteMapNode>
</siteMapNode>
<siteMapNode url="./Administration/Administration.aspx" title="Administration" >
<siteMapNode url="./Administration/UserBranchAssignment.aspx" title="Assign Users to Branches" />
</siteMapNode>
<siteMapNode url="./BusinessIntelligence/Dashboard.aspx" title="Business Intelligence Dashboard" >
</siteMapNode>
</siteMapNode>
</siteMap>

Menu Master Page file:

<%@ Master MasterPageFile="~/Masters/MenuLayout.master" Language="C#" CompileWith="Menu.master.cs" ClassName="Menu_master" %>

<asp:Content ID="SiteMapPathContent" ContentPlaceHolderID="SiteMapPathContentPlaceholder" Runat="server">

<asp:SiteMapPath ID="Crumbs" runat="server" CssClass="Heading"

RenderCurrentNodeAsLink="false"

PathSeparator="|"

CurrentNodeStyle-ForeColor="black"

RootNodeStyle-ForeColor="blue"

/>

</asp:Content>

<asp:Content ID="MenuContent" ContentPlaceHolderID="MenuPlaceHolder" Runat="server">

<asp:SiteMapDataSource ID="SiteMap" Runat="server" ShowStartingNode="False" StartFromCurrentNode="True" />

<asp:menu id="Menu" CssClass="Bold"

staticdisplaylevels="1"

maximumDynamicDisplayLevels="0"

orientation="Vertical"

datasourceid="SiteMap"

runat="server">

<staticmenuitemstyle forecolor="blue" />

</asp:menu>

</asp:Content>

An actual menu page: eg. ./Contracts/DocumentManagement/DocumentManagement.aspx--see the reference in the SiteMap file above:

<%@ Page Language="C#" MasterPageFile="~/Masters/Menu.master" CompileWith="DocumentManagement.aspx.cs" ClassName="DocumentManagement_aspx" Title="Contract Document Management Menu Page" %>

Yup: just the @Page directive: MasterPageFile attribute does everything we need.

Number of lines of code to create the menu: Zero!<%@ Page Language="C#" MasterPageFile="~/Masters/Menu.master" CompileWith="DocumentManagement.aspx.cs" ClassName="DocumentManagement_aspx" Title="Contract Document Management Menu Page" %>