Do you have tab on the menu?

[While writing this post, I was reminded of the scene in Back to the Future where Marty McFly goes into Lou’s diner in 1955 and orders a Tab (the predecessor to Diet Coke, first marketed in 1963) to which Lou replies "Tab? I can't give you a tab unless you order something. " Hence, the post title.]

In ASP.NET 2.0, there’s a great new set of controls and supporting technologies for providing site navigation to users. One of these is the Menu control. When you connect a Menu control with a SiteMapDataSource (which by default draws its navigational data from the XML file web.sitemap), it renders dynamic menus that allow users to navigate the site. If you’re new to the Menu control, start with this article.

During my last series of MSDN Events, I mentioned that I had seen a technique for turning the ASP.NET 2.0 Menu control into a tab strip. After asking around, my colleague Michael Earls pointed out this article he'd written a few months back. Michael shows a good approach, however I’m always a fan of keeping things as simple as possible. In this case, the simplicity of the technique I use here lies in the fact that it’s pretty much all done through properties of the Menu control itself. The only things added are two small graphics (more on that later).

For this example, here is the simple web.sitemap file that I’m using.:

 <sitemap xmlns="https://schemas.microsoft.com/AspNet/SiteMap-File-1.0">
    <sitemapnode title="Home" description="" url="default.aspx">
        <sitemapnode title="page 2" description="" url="default2.aspx" />
        <sitemapnode title="page 3" description="" url="default3.aspx" />
    </sitemapnode>
</sitemap>

Adding a Menu control to a page yields the default behavior as represented below. The top level (Home) is displayed, and if I mouse over it, the second level (Page 2, Page 3) is displayed.

Defaultmenucontrol

Defaultmenucontrol2

You might be thinking “well, that doesn’t look very tab-like”. Fortunately, we can hook into properties and child objects of the Menu control to coerce it into rendering something more tab-like. To accomplish this, we have to do a few things.

First, change the alignment of the menu to be horizontal and get everything up on one line. To do this, set the following properties:

 MaximumDynamicDisplayLevels="0" Orientation="Horizontal"StaticSubMenuIndent="0px"

Next, we need ourselves some ears. So whip yourself up some graphics representing the left and right side of the tabs, and remember their color because you’ll need it later. Assign them as the separators for the top and bottom of the menu items, which, since we changed the alignment, will come out at the left and right instead.

 StaticBottomSeparatorImageUrl="~/tabright.gif"StaticTopSeparatorImageUrl="~/tableft.gif"

Now, set the background color of the menu items (and the menu itself, or you’ll see slivers of white below the text of each menu) to the color you used for the tab graphics:

 <StaticMenuItemStyle BackColor="#99CCFF" /><StaticMenuStyle BackColor="#99CCFF" />

To distinguish the “active” tab, there are lots of things you can do. For simplicity, let’s just bold the font of the current tab. This is another way the Menu control helps us – by comparing the site map to the actual page we’re on, it knows which menu item (and in our case, tab) is the active one.

 <StaticSelectedStyle Font-Bold="True" />

So, the completed menu declaration in the .ASPX page looks like this (I added font-names to pretty things up):

 <asp:Menu ID="Menu1" runat="server" BorderColor="#99CCFF" DataSourceID="SiteMapDataSource1"MaximumDynamicDisplayLevels="0" Orientation="Horizontal" StaticBottomSeparatorImageUrl="~/tabright.gif"StaticDisplayLevels="2" StaticSubMenuIndent="0px" StaticTopSeparatorImageUrl="~/tableft.gif" Font-Names="tahoma,arial,helvetica,geneva;">   <StaticMenuItemStyle BackColor="#99CCFF" />   <StaticMenuStyle BackColor="#99CCFF" />   <StaticSelectedStyle Font-Bold="True" /></asp:Menu>

Below are a few screenshots of the tabs in action. I placed them in a master page along with a panel right below them whose back color is the same as the tabs. The content placeholder is inside the panel.

Tabmenucontrol

Tabmenucontrol2

So that’s it. You could probably get even fancier by using some CSS styles and connecting the menu items to those classes in the appropriate properties of the Menu control. See Michael’s article referenced above for information on that.