ASP.NET 2.0's Sophisticated Site Navigation Features

Every Web site needs to display navigation data that guides its users through the site. ASP.NET 2.0 provides excellent site-navigation features that provide very simple ways of storing and displaying site-navigation data in your Web applications. Apart from that, a site navigation API also provides a provider-based programming abstraction for accessing site navigation data. This article examines these new site-navigation features and explains how to take advantage of them in your Web applications. Along the way, it demonstrates how the new site-navigation controls that are built on top of the Site Navigation classes, such as the Menu, TreeView, SiteMapPath, and SiteMapDataSource controls, consume and display navigation data without being aware of data-store-specific storage issues.

Site Navigation Structure and the Controls

You represent the navigation structures for a Web site through a file called web.sitemap. The Web.sitemap file contains a single top-level siteMap element. Nested within the siteMap element is at least one siteMapNode element. A site map must always contain a top-level siteMapNode. The Site Navigation feature requires a single root siteMapNode to ensure that you will always converge on a single well-known node when walking up through the hierarchy of the nodes. You can nest as many siteMapNode elements beneath the root siteMapNode element as needed. Additionally, you can nest siteMapNode elements to any arbitrary depth.

The siteMapNode element usually contains the Url, Title, and Description attributes:

  • The Url attribute indicates a virtual path that corresponds to a page in your application. It can also contain paths to pages in other applications, or URLs that point at completely different Web sites. You should use relative paths when specifying the Urls in the web.sitemap file.
  • The Title attribute displays the textual content when rendering the UI for navigational data. For example, the SiteMapPath control uses the Title attribute to display the text of the hyperlinks in the control.
  • If the siteMapNode contains a Description attribute, you use that information to display tooltips or ALT text.

Once you have the site-navigation structure available in the web.sitemap file, you then can consume that information by using the following two steps:

  1. Add a SiteMapDataSource control to your page. This control will automatically consume the contents of the web.sitemap file and make it readily available for the hierarchical data bound controls.
  2. Bind the data bound controls such as SiteMapPath, TreeView, and Menu to the SiteMapDataSource control and then display the site navigation information.

Now that you understand the procedures involved in displaying the site navigation information, it's time to briefly define the graphical site navigation controls:

  • SiteMapPath—This is a breadcrumb control that retrieves the user's current page and displays the hierarchy of pages. Since the entire hierarchy is displayed through this control, it enables the users to navigate back to other pages in the hierarchy. SiteMapPath works exclusively with the SiteMapDataSource control.
  • TreeView—This control provides a vertical user interface to expand and collapse selected nodes on a Web page, as well as providing check box functionality for selected items. By setting the SiteMapDataSource control as the data source for the TreeView control, you can leverage the automatic data binding capabilities of the TreeView control.
  • Menu—This control provides a horizontal or vertical user interface that also can display additional sub-menus when a user hovers over an item. When you use the SiteMapDataSource control as the data source, data binding will be automatic.

Now that you have seen the different controls, follow an example that exercises these controls.

Displaying Site Navigation Data from the Web.sitemap File

This example uses the TreeView control to display hierarchical information about the site structure by using the contents of the web.sitemap file. It creates a new ASP.NET Web Site named SiteNavigation and then adds a new web.sitemap file to the site. The web.sitemap file looks as follows:

<?xml version="1.0" encoding="utf-8" ?>
<siteMap>
<siteMapNode title="Default" description="Home" url="Default.aspx" >
   <siteMapNode title="Members" description="Members"
                url="Members.aspx">>
      <siteMapNode title="My Account" description="My Account"
                   url="MyAccount.aspx" />
          <siteMapNode title="Products" description="Products"
                       url="Products.aspx" />
   </siteMapNode>
   <siteMapNode title="Administration" description="Administration"
                url="~/Admin/Default.aspx">
      <siteMapNode title="Customer" description="Customer Admin"
                   url="~/Admin/Customer/default.aspx" />
      <siteMapNode title="Products Admin"
                   description="Products Admin"
                   url="~/Admin/ProductsAdmin.aspx" />
  </siteMapNode>
</siteMapNode>
</siteMap>

As you can see, the web.sitemap file specifies the list of nodes that specify the navigation structure of the site, which can be completely independent of the site folder layout or other structures.

Create a new master page named Navigation.master and modify its code to look like the following:

<%@ Master Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
   <title>Master Page</title>
</head>
<body>
   <form id="form1" runat="server">
   <div>
      <table style="width: 100%; height: 100%" border="1">
         <tr>
            <td style="width: 10%">
               <asp:TreeView ID="TreeView1" Runat="server"
                             DataSourceID="SiteMapDataSource1"
                             ExpandDepth="2"
                             ShowExpandCollapse="False"
                             NodeIndent="10">
                  <LevelStyles>
                     <asp:TreeNodeStyle Font-Bold="True"
                                        Font-Underline="False"/>
                     <asp:TreeNodeStyle Font-Italic="True"
                                        Font-Underline="False" />
                     <asp:TreeNodeStyle Font-Size="X-Small" 
                                        ImageUrl="~/Images/bullet.gif"
                                        Font-Underline="False" />
                  </LevelStyles>
                  <NodeStyle ChildNodesPadding="10" />
                     </asp:TreeView>
            </td>
            <td style="width: 100px">
               <asp:contentplaceholder id="ContentPlaceHolder1"
                                       runat="server">
               </asp:contentplaceholder>
            </td>
         </tr>
      </table>
      <asp:SiteMapDataSource ID="SiteMapDataSource1" Runat="server"/>
   </div>
   </form>
</body>
</html>

As you can see, the code places SiteMapDataSource control in the page and uses it as the data source control for the treeview named TreeView1. The TreeView control also defines the styles for the different node levels. In this example, because you have a SiteMapDataSource placed on the page, it will specifically look for a file with the name web.sitemap by default. It will read the contents of the web.sitemap file and consume that information as a data source control.

Once the information is available in a SiteMapDataSource control, you then can consume it from a data-bound control. In this example, you used the TreeView control as a data-bound control and set the DataSourceID property of the TreeView control to the ID value of the SiteMapDataSource.

Now that you have created the master page, you can create a content page that inherits the contents from it. Create a content page named Default.aspx and modify its code to look like the following:

<%@ Page Language="C#" MasterPageFile="~/Navigation.master"
         Title="Default Page"%>
<asp:Content ContentPlaceHolderID="ContentPlaceHolder1"
             ID="Content1" Runat="Server">
   This is the default page
</asp:Content>

The code combines the master page and the content page and then inserts contents in appropriate locations by using the asp:Content element. You simply have some text information that indicates that this content is coming from the default page. If you execute the above code, you will see an output that is somewhat similar to Figure 1.

Figure 1. Default Page Output

The left navigation contents in Figure 1 are produced by the master page, and the main body of the page is produced by default.aspx. Clicking on any of the hyperlinks in the treeview takes you to the page url that is specified in the web.sitemap file.

ASP.NET 2.0's Sophisticated Site Navigation Features

Displaying the Site Navigation Information Using a Menu Control

So far, you have seen how to display the site navigation structure using the TreeView control. In this section, you will utilize the Menu control and see how you can use that as a data bound control, binding it with the SiteMapDataSource control.

Go back to the Navigation.master page and modify its code to look like the following:

<%@ Master Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
   <title>Master Page</title>
</head>
<body>
   <form id="form1" runat="server">
   <div>
      <table style="width: 100%; height: 100%" border="1">
         <tr height="100px">
<td colspan="2" align="left">
<asp:Menu ID="Menu1" Runat="Server"
          DataSourceID="SiteMapDataSource1">
</asp:Menu>
</td>
         </tr>
         <tr>
            <td style="width: 10%">
                <asp:TreeView ID="TreeView1" Runat="server"
                              DataSourceID="SiteMapDataSource1"
                              ExpandDepth="2"
                              ShowExpandCollapse="False"
                              NodeIndent="10">
                   <LevelStyles>
                      <asp:TreeNodeStyle Font-Bold="True"
                                         Font-Underline="False"/>
                      <asp:TreeNodeStyle Font-Italic="True"
                                         Font-Underline="False" />
                      <asp:TreeNodeStyle Font-Size="X-Small"
                                         ImageUrl="~/Images/bullet.gif"
                                         Font-Underline="False" />
                   </LevelStyles>
                   <NodeStyle ChildNodesPadding="10" />
                </asp:TreeView>
            </td>
            <td style="width: 100px">
                <asp:contentplaceholder id="ContentPlaceHolder1"
                                        runat="server">
                </asp:contentplaceholder>
            </td>
         </tr>
      </table>
        <asp:SiteMapDataSource ID="SiteMapDataSource1"
                               Runat="server"/>
   </div>
   </form>
</body>
</html>

The only change you made from the previous section's example is the addition of the following code (which is related to the menu control):

<tr height="100px">
   <td colspan="2" align="left">
   <asp:Menu ID="Menu1" Runat="Server"
             DataSourceID="SiteMapDataSource1">
   </asp:Menu>
   </td>
</tr>

You declared a menu control and set its DataSourceID property to the id of the SiteMapDataSource control. That's all you need to do to leverage the menu control for displaying the site navigation structure from the web.sitemap file. When you execute the above code, you will see the output in Figure 2.

Figure 2. Results of the Menu Control for Displaying the Site Navigation Structure

In Figure 2, the menus are arranged in horizontal fashion by default. You also can arrange them vertically by configuring the orientation. The setting in the Orientation property can be either Vertical or Horizontal.

Displaying Breadcrumb Navigation

If you have done any serious Web development, you definitely have heard the term "breadcrumb." Basically, breadcrumb navigation allows you to display the current page's context within the site structure. The benefit of a breadcrumb is that it makes obvious the ways in which the pages have been grouped and allows the user both to navigate between these pages and understand the site arrangement structure.

Traditionally with ASP.NET 1.x, displaying breadcrumbs requires you to create manual plumbing code that reads information from an external source to display breadcrumbs. However, with ASP.NET 2.0, this is built into the framework itself and using it requires only one line of declaration. As an example of this new control, modify your Navigation.master file to look like the following:

<%@ Master Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
   <title>Master Page</title>
</head>
<body>
   <form id="form1" runat="server">
   <div>
      <table style="width: 100%; height: 100%" border="1">
         <tr height="100px">
            <td colspan="2" align="left">
            <asp:Menu ID="Menu1" Runat="Server"
                      DataSourceID="SiteMapDataSource1">
            </asp:Menu>
            </td>
         </tr>
         <tr height="100px">
            <td colspan="2" align="left">
                Currently Selected Page is: <asp:SiteMapPath
                Runat="Server"
                ID="SiteMapPath1"></asp:SiteMapPath>
            </td>
         </tr>
         <tr>
            <td style="width: 10%">
               <asp:TreeView ID="TreeView1" Runat="server"
                             DataSourceID="SiteMapDataSource1"
                             ExpandDepth="2"
                             ShowExpandCollapse="False"
                             NodeIndent="10">
                  <LevelStyles>
                     <asp:TreeNodeStyle Font-Bold="True"
                                        Font-Underline="False"/>
                     <asp:TreeNodeStyle Font-Italic="True"
                                        Font-Underline="False" />
                     <asp:TreeNodeStyle Font-Size="X-Small"
                                        ImageUrl="~/Images/bullet.gif"
                                        Font-Underline="False" />
                  </LevelStyles>
                  <NodeStyle ChildNodesPadding="10" />
               </asp:TreeView>
            </td>
            <td style="width: 100px">
               <asp:contentplaceholder id="ContentPlaceHolder1"
                                       runat="server">
               </asp:contentplaceholder>
            </td>
         </tr>
      </table>
      <asp:SiteMapDataSource ID="SiteMapDataSource1" Runat="server"/>
   </div>
   </form>
</body>
</html>

Because most of the code is similar to the previous example, you can concentrate only on the lines of code that are different. You added a new tr element that contains the SiteMapPath control in it:

<tr height="100px">
   <td colspan="2" align="left">
      Currently Selected Page is: <asp:SiteMapPath
         Runat="Server"
         ID="SiteMapPath1"></asp:SiteMapPath>
   </td>
</tr>

Once you add the SiteMapPath control, it automatically binds to the SiteMapDataSource control and displays the context of the current page in the site-navigation hierarchy.

ASP.NET 2.0's Sophisticated Site Navigation Features

Now that you have modified the master page, create a new content page named Members.aspx file and modify its code to look like the following:

<%@ Page Language="C#" MasterPageFile="~/Navigation.master"
         Title="Members Page"%>
<asp:Content ContentPlaceHolderID="ContentPlaceHolder1"
             ID="Content1" Runat="Server">
   This is the members page
</asp:Content>

Now, navigate to the default.aspx file using the browser. In the default page, click on the Members hyperlink using the menu or the treeview control. Figure 3 displays the resulting output.

Figure 3. The Breadcrumb Control in Action

The screenshot in Figure 3 shows the breadcrumb control in action. Because you have navigated to the members page, the breadcrumb control displays the link to the default page as well as the description of the current page.

Obtain Site Navigation Data Programmatically

You also can retrieve site navigation data programmatically. One of the important classes that you need to use when doing this is the SiteMap class. This class provides a number of static methods, the most important one being the CurrentNode property. For example, you can invoke the SiteMap.CurrentNode to reference a piece of navigation data matching the currently executing page. The CurrentNode property returns an instance of a SiteMapNode object that corresponds to the current page. Similar to the previous examples, the site navigation feature determines the correct node to return based upon navigation data that is stored in the web.sitemap file.

Once you have an instance of the SiteMapNode object instance, you can perform the following tasks:

  • Retrieve properties of a node, including Url, Title, and Description
  • Obtain a node's parent as well as a node's children
  • Navigate through the sibling nodes before and after the current node
  • Obtain a reference to the SiteMapProvider instance that returned this node

Once you have a reference to a SiteMapProvider, you can search the site navigation data for a specific node based on URL. This allows you to obtain references to SiteMapNode instances anywhere in your site-navigation data. The combination of finding arbitrary SiteMapNode instances and the ability to navigate through site navigation data from any SiteMapNode allows you to easily walk through your site's navigation data.

Apart from the web.sitemap file, you also can store the navigational data in other data stores, such as some other XML file or relational data in the database. In that case, you then can author a custom provider that derives from SiteMapProvider. SiteMapProvider instances are responsible for returning SiteMapNode instances that can then be consumed by pages and server controls.

The following example enhances the Members.aspx page by adding some code in the Page_Load event. Here is the modified code of the Members.aspx page:

<%@ Page Language="C#" MasterPageFile="~/Navigation.master"
         Title="Members Page"%>
<script runat="Server">
   void Page_Load(object sender, EventArgs e)
   {
      Response.Write("The currently selected root node is: " +
                      SiteMap.CurrentNode.Description + "<br>");
      Response.Write("The Parent for the currently selected node
                      is : "  +
                     SiteMap.CurrentNode.ParentNode.Description);
   }
</script>
<asp:Content ContentPlaceHolderID="ContentPlaceHolder1"
             ID="Content1" Runat="Server">
   This is the members page
</asp:Content>

You use the code in Page_Load to retrieve the details of the currently selected node. Once you've obtained the reference to the current node, you then can retrieve the description as well. The code also demonstrates how to get the reference to the parent node from the current node by invoking the current node's ParentNode property. If you run the above code, you will get an output that is somewhat similar to Figure 4.

Figure 4. The Details of the Currently Selected Node

In the above screenshot, the top of the page displays the description of the currently selected node, as well as the description of the parent node.

Sophisticated Site Navigation for Your Web Applications

ASP.NET 2.0 site navigation provides a number of new productivity enhancements that should excite developers. The features you saw in this article provide a good representation of ASP.NET 2.0's site-navigation features. Once you get familiar with them, you will have a rich set of tools and techniques for creating sophisticated site navigational capabilities in your Web applications.



Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • With JRebel, developers get to see their code changes immediately, fine-tune their code with incremental changes, debug, explore and deploy their code with ease (both locally and remotely), and ultimately spend more time coding instead of waiting for the dreaded application redeploy to finish. Every time a developer tests a code change it takes minutes to build and deploy the application. JRebel keeps the app server running at all times, so testing is instantaneous and interactive.

  • Hurricane Sandy was one of the most destructive natural disasters that the United States has ever experienced. Read this success story to learn how Datto protected its partners and their customers with proactive business continuity planning, heroic employee efforts, and the right mix of technology and support. With storm surges over 12 feet, winds that exceeded 90 mph, and a diameter spanning more than 900 miles, Sandy resulted in power outages to approximately 7.5 million people, and caused an estimated $50 …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds