Decrease Font Size
Increase Font Size
   BLOG

ASP NET Horizontal Menu Control

by bryian 14. December 2009 18:18

ASP.NET menu control safari|

Problem displaying asp .net menu control in Google Chrome|

Breadcrumb (Sitemappath) Control|

ASP.NET Menu control|

Displaying Menu Control Horizontal With SubMenus|

ASP.NET Menu AccessKey|

ASP.NET Menu Target

Last Updated - 02/26/2010

  • Removed PathSeparator of SiteMapPath before the root node as suggested by The Code Project member, kentex2000.
  • Added SiteMap.CurrentNode != null to SiteMap_SiteMapResolve method.

Last Updated - 02/03/2010

Introduction

A few weeks ago, I was working on an ASP.NET web application and need a simple horizontal menu with submenu. I decided to use ASP.NET Menu control, just drag and drop the control on to the page. Simple enough, but the control does not provide access key and target window support on menu item. I have put together a tutorial on how to:

  1. Include an access key attribute
  2. Include a target attribute
  3. Include a Site Map Path


Figure 1
Sample results

 

Getting Started

Here is the structure of my project. You are welcome to download this demo.

Figure 2
Project Structure

Putting everything together

First, add a Site Map to the website project. Open the web.sitemap file and populate it with your navigation data and structures. To underline certain character of the menu title, we can use the HTML underline tag (<u></u>). In order to parse the XML flawlessly we must replace the less than sign (<) with & lt; (no spaces). Then, include an accesskey and target attribute with a value to each siteMapNode. See below for example.

Site Map

Listing 1

<siteMapNode>
      <siteMapNode url="Default.aspx" title="& lt;u>H& lt;/u>ome" description="Home" 
                   accesskey="H" />
      <siteMapNode url="~/Views/Menu1.aspx" title="<u>M</u>enu1"  
                   description="Menu1" accesskey="M" />
        <siteMapNode url="~/Views/Menu2.aspx" title="M<u>e</u>nu2" 
                     description="Menu2" accesskey="E" />
    
    <siteMapNode url="~/Views/Menu3.aspx" title="Me<u>n</u>u3" 
                 description="Menu3" accesskey="N" target="_blank" />
        
    <siteMapNode url="~/Views/Menu4.aspx" title="Men<u>u</u>4" 
                 description="Menu4" accesskey="U">
      <siteMapNode url="~/Views/Menu4Sub1.aspx" title="Menu4<u>S</u>ub1" 
                   description="Menu4Sub1" 
                   accesskey="S" />
      <siteMapNode url="~/Views/Menu4Sub2.aspx" title="Menu4Su<u>b</u>2" 
                   description="Menu4Sub2" 
                   target="_blank" accesskey="B" />
    </siteMapNode>
……
….
  </siteMapNode>
</siteMap>

Master Page

Add a Master Page to the website project. Drag a SiteMapDataSource control on to the page and then the menu control and wrap the menu control inside a div tag. The details description of each menu property can be found on Menu Properties Menu Properties. Set the staticdisplaylevels ="2" and orientation="Horizontal" to display the menu control in horizontal mode. We can use an inline style sheets or place the CSS style in an external file. In this tutorial, the CSS style is located in style.css file. See listing 2.

Listing 2

<asp:SiteMapDataSource id="MenuSource" runat="server" />
<div class="background">
  <asp:menu id="NavigationMenu" CssClass="NavigationMenu"  
        staticdisplaylevels="2" DynamicHorizontalOffset="1"
        staticsubmenuindent="1px" MaximumDynamicDisplayLevels="4"
        orientation="Horizontal"   
        DynamicPopOutImageUrl="~/Images/right-arrow.gif" 
        StaticPopOutImageUrl="~/Images/drop-arrow.gif"
        datasourceid="MenuSource"    
        runat="server" Height="30px">

        <staticmenuitemstyle ItemSpacing="10" CssClass="staticMenuItemStyle"/>
        <statichoverstyle CssClass="staticHoverStyle" />
       <StaticSelectedStyle CssClass="staticMenuItemSelectedStyle"/> 
        <DynamicMenuItemStyle CssClass="dynamicMenuItemStyle" />      
        <dynamichoverstyle CssClass="menuItemMouseOver" />
        <DynamicMenuStyle CssClass="menuItem" />
       <DynamicSelectedStyle CssClass="menuItemSelected" />
     
       <DataBindings>        
             <asp:MenuItemBinding DataMember="siteMapNode" 
                    NavigateUrlField="url" TextField="title"  
                    ToolTipField="description" />
        </DataBindings>

      </asp:menu>
</div>

Drag a SiteMapPath control on to the page. The purpose of this control is to display navigation path that shows the user the current page location. See listing 3.

Listing 3

<div id="e">
       <asp:SiteMapPath ID="SiteMapPath1" runat="server" 
                RenderCurrentNodeAsLink="true" 
                CssClass="currentNodeStyle"
            PathSeparator=" >> ">
            <PathSeparatorStyle ForeColor="#5D7B9D" CssClass="currentNodeStyle" />
            <CurrentNodeStyle ForeColor="#333333" CssClass="currentNodeStyle" />
            <NodeStyle ForeColor="#7C6F57"  CssClass="currentNodeStyle"  />
            <RootNodeStyle  ForeColor="#5D7B9D" CssClass="currentNodeStyle"  />
    </asp:SiteMapPath> 
</div>  

Master Page code behind

In the Master Page code behind, include a MenuItemDataBound and SiteMapResolve event handlers on to the Page_Load event. The purpose of the former event is to insert the target attribute value and create access key for the menu item before it is rendered or displayed in a Menu control. The latter event is to modify the text displayed by the SiteMapPath control.

Listing 4

NavigationMenu.MenuItemDataBound += new MenuEventHandler(NavigationMenu_MenuItemDataBound);
SiteMap.SiteMapResolve += new SiteMapResolveEventHandler(SiteMap_SiteMapResolve);

Below is the implementation of the NavigationMenu_MenuItemDataBound method. The MenuItemDataBound event occurs when a menu item in a Menu control is bound to data. That being said, it will loop through each siteMapNode and look for the accesskey and target attribute. There is a target property associated with the menu item and we can set its target window with the target attribute value. See listing 5.

Listing 5

void NavigationMenu_MenuItemDataBound(object sender, MenuEventArgs e)
    {
        SiteMapNode node = (SiteMapNode)e.Item.DataItem;
       
        //set the target of the navigation menu item (blank, self, etc...)
        if (node["target"] != null)
        {
            e.Item.Target = node["target"];
        }
        //create access key button
        if (node["accesskey"] != null)
        {
            CreateAccessKeyButton(node["accesskey"] as string, node.Url);
        }
    }

To get the access key to work, add a Panel control on to the master page and a JavaScript function to redirect the webpage to the one that is specified. See below.

Listing 6

<asp:Panel ID="AccessKeyPanel" runat="server" />
<script type="text/javascript">
 function navigateTo(url) {
    window.location = url;
 }
</script>

Below is the implementation of the CreateAccessKeyButton method. Create an HtmlButton control dynamically and attach an onclick event to it. Set the style.left property to -2555px to hide the control. A complete list of access key in different browsers is available here.

Listing 7

//create access key button
    void CreateAccessKeyButton(string ak, string url)
    {
        HtmlButton inputBtn = new HtmlButton();
        inputBtn.Style.Add("width", "1px");
        inputBtn.Style.Add("height", "1px");
        inputBtn.Style.Add("position", "absolute");
        inputBtn.Style.Add("left", "-2555px");
        inputBtn.Style.Add("z-index", "-1");
        inputBtn.Attributes.Add("type", "button");
        inputBtn.Attributes.Add("value", "");
        inputBtn.Attributes.Add("accesskey", ak);
        inputBtn.Attributes.Add("onclick", "navigateTo('" + url + "');");

        AccessKeyPanel.Controls.Add(inputBtn);
    }

The SiteMap.SiteMapResolve event get trigger when the CurrentNode property is accessed. It will call the ReplaceNodeText method recursively and replace the HTML underline tag. See listing 8.

Listing 8

SiteMapNode SiteMap_SiteMapResolve(object sender, SiteMapResolveEventArgs e)
    {
        if (SiteMap.CurrentNode != null)
        {
            SiteMapNode currentNode = SiteMap.CurrentNode.Clone(true);
            SiteMapNode tempNode = currentNode;
            tempNode = ReplaceNodeText(tempNode);

            return currentNode;
        }
        return null;
    }

    //remove <u></u> tag recursively
    internal SiteMapNode ReplaceNodeText(SiteMapNode smn)
    {
        //current node
        if (smn != null && smn.Title.Contains("<u>"))
        {
            smn.Title = smn.Title.Replace("<u>", "").Replace("</u>", "");
        }

        //parent node
        if (smn.ParentNode != null)
        {
            if (smn.ParentNode.Title.Contains("<u>"))
            {
                SiteMapNode gpn = smn.ParentNode;
                smn.ParentNode.Title = smn.ParentNode.Title.Replace("<u>", "").Replace("</u>", "");
                smn = ReplaceNodeText(gpn);
            }
        }
        return smn;
    }

Using the Code

Since the menu is in the master page, right click the website project, add new item, Web Form and check the Select Master Page checkbox.

Points of Interest

The hover menu appears to not working on mobile devices. To remedy this problem, I include a TreeView control and set its visible property to false. This control expands its entire node by default. That will take care of the mentioned problem. In the code behind, hide the Menu control and show the TreeView control if requesting browser is a mobile device. See listing 9.

Listing 9

protected void Page_Load(object sender, EventArgs e)
    {
	if (Request.Browser.IsMobileDevice)
        {
            NavigationMenu.Visible = false;
            NavigationTreeView.Visible = true;
        }
}

When I tested the menu on IE 8, the hover menu did not render correctly. To overcome this problem, I set the DynamicMenuStyle z-index to 200, see style.css. The submenu is also not working with Google Chrome. After some research, I found the solution for it. See listing 10.

Listing 10

protected void Page_Load(object sender, EventArgs e)
    {
	if (Request.UserAgent.IndexOf("AppleWebKit") > 0)
        {
            Request.Browser.Adapters.Clear();
            NavigationMenu.DynamicMenuStyle.Width = Unit.Pixel(120);
        }
}

New Update

I have received several complaints from the reader concerning the menu control not displaying correctly on Safari and Google Chrome browsers. Somehow the menu items are stacked on each other and the submenu widths are gapped apart. After doing some research, I found the answer here, see listing 11. To fix the submenu width, remove the display:block from the dynamicMenuItemStyle in the css file.

Listing 11

protected override void AddedControl(Control control, int index)
    {
        if (Request.ServerVariables["http_user_agent"].IndexOf("Safari", StringComparison.CurrentCultureIgnoreCase) != -1)
            this.Page.ClientTarget = "uplevel";

        base.AddedControl(control, index);
    }

I also rewrite the logic to detect mobiles browser with the code from Vincent Van Zyl. See listing 12.

Listing 12

    public static readonly string[] mobiles =
          new[]
                {
                    "midp", "j2me", "avant", "docomo", 
                    "novarra", "palmos", "palmsource", 
                    "240x320", "opwv", "chtml",
                    "pda", "windows ce", "mmp/", 
                    "blackberry", "mib/", "symbian", 
                    "wireless", "nokia", "hand", "mobi",
                    "phone", "cdm", "up.b", "audio", 
                    "SIE-", "SEC-", "samsung", "HTC", 
                    "mot-", "mitsu", "sagem", "sony"
                    , "alcatel", "lg", "eric", "vx", 
                    "NEC", "philips", "mmm", "xx", 
                    "panasonic", "sharp", "wap", "sch",
                    "rover", "pocket", "benq", "java", 
                    "pt", "pg", "vox", "amoi", 
                    "bird", "compal", "kg", "voda",
                    "sany", "kdd", "dbt", "sendo", 
                    "sgh", "gradi", "jb", "dddi", 
                    "moto", "iphone"
                };

    public static bool isMobileBrowser()
    {
        //GETS THE CURRENT USER CONTEXT
        HttpContext context = HttpContext.Current;

        //FIRST TRY BUILT IN ASP.NT CHECK
        if (context.Request.Browser.IsMobileDevice)
        {
            return true;
        }
        //THEN TRY CHECKING FOR THE HTTP_X_WAP_PROFILE HEADER
        if (context.Request.ServerVariables["HTTP_X_WAP_PROFILE"] != null)
        {
            return true;
        }
        //THEN TRY CHECKING THAT HTTP_ACCEPT EXISTS AND CONTAINS WAP
        if (context.Request.ServerVariables["HTTP_ACCEPT"] != null &&
            context.Request.ServerVariables["HTTP_ACCEPT"].ToLower().Contains("wap"))
        {
            return true;
        }
        //AND FINALLY CHECK THE HTTP_USER_AGENT 
        //HEADER VARIABLE FOR ANY ONE OF THE FOLLOWING
        if (context.Request.ServerVariables["HTTP_USER_AGENT"] != null)
        {
            for (int i = 0; i < mobiles.Length; i++)
            {
                if (context.Request.ServerVariables["HTTP_USER_AGENT"].
                                                    ToLower().Contains(mobiles[i].ToLower()))
                {
                    return true;
                }
            }
        }

        return false;
    }

Add the code shown below in the Page_Load event.

Listing 13

if (isMobileBrowser())
        {
            NavigationMenu.Visible = false;
            NavigationTreeView.Visible = true;
        }

Conclusion

If you find any bugs or disagree with the contents, please drop me a line and I'll work with you to correct it.

Tested on IE 6.0/7.0/8.0, Google Chrome, Firefox, Safari

IE, Firefox, Google Chrome, Safari

History

  • 02/03/2010 - Fixed the Menu display problem in Safari and Google Chrome browsers, added new logic to detect mobiles browser

Resources

Access in different Browsers
ASP.NET Menu Control Cannot Work in Google Chrome browser and Apple Safari browser
Detecting a mobile browser in ASP.NET
IE8 and the ASP.NET Menu control
Menu Properties
Menu..::.MenuItemDataBound Event
Problem displaying asp .net menu control in Google Chrome
SiteMap..::.SiteMapResolve Event

Watch this script in action

Demo

Downloads

Download

Comments

12/9/2009 4:49:59 AM #

SEO Surrey

Horizontal menu tool is something new to me and may need some time to get to used too.

SEO Surrey United States

12/10/2009 10:34:35 PM #

trackback

ASP NET Horizontal Menu Control blog.ysatech.com/.../ASP-NET-Horizontal-Menu-Control.aspx" rel="nofollow">blog.ysatech.com/.../...rizontal-Menu-Control.aspx

ASP NET Horizontal Menu Control blog.ysatech.com/.../ASP-NET-Horizontal-Menu-Control

Twitter Mirror

12/10/2009 10:56:21 PM #

trackback

ASP NET Horizontal Menu Control

You've been kicked (a good thing) - Trackback from DotNetKicks.com

DotNetKicks.com

12/11/2009 6:22:44 AM #

John Katsiotis

Check CSS Friendly Control Adapters http://www.codeplex.com/cssfriendly

It's the same thing but more easy to implement. ;)

John Katsiotis Greece

12/13/2009 7:54:58 AM #

Digital SLR Cameras

It's new to me. Still i haven't try it but after reading this post, i have decided to try it.

Digital SLR Cameras United States

12/18/2009 2:14:51 AM #

Learn And Master Guitar

Great new direction. Crisp, clean, refreshing.

Learn And Master Guitar United States

12/25/2009 6:12:07 AM #

garden d�cor

Hey saw your post today bryian & I must say you have done a great job in understanding the basics of this topic & working on the updates. I am looking forward to more articles from you on the same topic.

garden d�cor United States

12/29/2009 2:08:53 PM #

Gold coast holiday apartments

Thanks in advance and thanks tremendously for being so generous. Alot of people sell these things online. Nice to see people giving them away. Google’s known for being free.

Gold coast holiday apartments United States

1/1/2010 8:13:50 PM #

pingback

Pingback from windows7serials.com

ASP NET Horizontal Menu Control | Windows 7 Serials

windows7serials.com

1/1/2010 11:48:35 PM #

Web Developer

Nice way to implement access key support. And thanks for putting up the demo and source code as its easy for someone to straight away use it in their projects.

Web Developer United Kingdom

1/2/2010 5:20:06 AM #

Voytek - Elegant Portfolios for Crative People

This is a interesting article. I myself use CSS Friendly Control Adapters. They are not perfect but at least give me some control over menu style. Don't care much about access keys but I'm going to use Listing 5.

Voytek - Elegant Portfolios for Crative People United States

1/3/2010 11:25:59 AM #

Steve Costello

I'll have to agree with @John Katsiotis. The .net Menu control is probably fine for something like prototyping, but past that, I wouldn't use it. The biggest problem with it is that it renders HTML tables. Getting past the whole "OMG, don't use tables for layout" argument, using tables for a menu truly is not syntactical. Using unordered lists has long been shown to be the best way to render menus, especially menus that are hierarchical in nature. There are several options out there, including the one John mentions. The Telerik Menu control is also quite nice (using it in a project right now, in fact), however, it is not free like the CSS Friendly Control Adapter set is.

Steve Costello United States

1/3/2010 1:57:58 PM #

Chester

Asp.net 2.0 menu control is no longer working in IE 8.

Chester Canada

1/4/2010 9:15:31 AM #

Swarovski perlen

Admiring the time and effort you put into your blog and detailed information you offer!

Swarovski perlen United States

1/5/2010 10:24:37 AM #

bryian

Chester,

I have tested this menu on IE 8 and it work fine.

Steve & John ,

I'll definitely try out the CSS adapter the next time.

Thanks,
Bryian Tan

bryian United States

1/10/2010 11:48:06 AM #

australian pr

Forwarded this to some friends, appreciate your advice

australian pr India

1/10/2010 6:37:19 PM #

Reverse Osmosis Water

Thanks for sharing the tutorial with us. It is very detailed, and the horizontal menu control will definitely come in handy. Appreciate your effort. Thanks.

Reverse Osmosis Water United States

1/12/2010 2:53:52 AM #

Ashish Kalmegh

Its better to have a horizontal menu rather than having a vertical menu . As its looks more professional and user friendly .

I will surely use your way . Thanks

Ashish Kalmegh India

1/13/2010 11:40:38 PM #

Florida Detox

This is such a great resource that you are providing and you give it away for free!! bryian I enjoy seeing websites that understand the value of providing a prime resource for free. I truly loved reading your post. Thanks!

Florida Detox United States

1/18/2010 12:39:55 PM #

amazon tours

Awesome post! Interesting info to know.

amazon tours India

1/20/2010 7:56:44 AM #

sikat ang pinoy

I found your blog on Google and read a few of your other posts. I just added you to my Google News Reader. Keep up the good work. Look forward to reading more from you in the future.

sikat ang pinoy United States

1/21/2010 8:30:00 PM #

SEO

Excellent post.I want to thank you for this informative read, I really appreciate sharing this great post. Keep up your work…

SEO United States

1/24/2010 1:09:30 AM #

renantech

I like blogengine.net powered by asp.net it is good for blog commenting it bring huge of backlinks and traffic.

renantech United States

1/26/2010 2:18:33 PM #

business opportunities from home

I’m impressed, you know what you’re talking about

business opportunities from home United Kingdom

1/26/2010 4:31:04 PM #

golf cart accessories

Hey hi bryian I am a fellow blogger in the same area of study as your's. Where do you update your information about these features from? Any study material or website you would recommend?

golf cart accessories United States

1/26/2010 5:55:17 PM #

mens diamond rings

Hi bryian, Me & my fellow classmates use your blogs as our reference materials. We look out for more interesting posts from your end about the same topic . Even the future updates about this topic would be of great help.

mens diamond rings United States

1/27/2010 12:34:42 AM #

Apex Professionals

This is a cool screen idea ! It is very interesting indeed.Thank you for your info.i love to read all info.This article gives the light in which we can observe the reality.

Apex Professionals United States

1/28/2010 7:16:09 AM #

web hosting coupons

Hi,
I Think this is really a great and very technical post for most of the interested people and i like it very much because i think this can be very beneficial for all of us. I am really impressed to know about that.
So i hope you will share some thing very interesting in the near upcoming future. Thanks for your support.

web hosting coupons United States

1/28/2010 12:15:26 PM #

solar hot water

Don’t stop blogging! It’s nice to read a sane commentary for once

solar hot water United States

1/28/2010 6:33:22 PM #

renantech

I like blogengine because it is an open source .net blogging project and made to desire a better blog platform. Godaddy was able to provide this services.

renantech United States

1/29/2010 12:58:43 PM #

make money online

Intimately, the post is in reality the greatest on this worthy topic. I fit in with your conclusions and will thirstily look forward to your coming updates. Just saying thanks will not just be adequate, for the extraordinary clarity in your writing. I will immediately grab your rss feed to stay abreast of any updates. Authentic work and much success in your business efforts!

make money online United States

1/29/2010 5:09:50 PM #

brisbane airport car rental

Really appreciate this post. It’s hard to sort the good from the bad sometimes, but I think you’ve nailed it!

brisbane airport car rental United States

1/30/2010 6:43:11 PM #

project management software

Thanks , It will really help me . i was looking got menu solution for my project  and now  i found it, Many Thanks

David

project management software United States

1/31/2010 5:02:18 AM #

Blister Packaging

Appreciate the tutorial! Learning about the horizontal menu control will definitely be useful for me. Thanks for sharing.

Blister Packaging United States

1/31/2010 5:46:59 PM #

utah toyota dealer

Great work buddy, keep it up

utah toyota dealer India

1/31/2010 7:17:43 PM #

dstarlight

an interesting ... Smile


Still Learning
Ace dstarlight

dstarlight Indonesia

2/3/2010 9:01:24 PM #

pabx panasonic

very nice thank's Smile

pabx panasonic Indonesia

2/5/2010 3:53:53 AM #

Boca Raton SEO

Nice Article, keep on the good work!

Boca Raton SEO Iceland

2/5/2010 4:41:02 AM #

antivirus firewall

Great post, very informative, thank you for sharing!

antivirus firewall United States

2/5/2010 11:55:30 AM #

peninggi badan

I was very impressed with your tutorial ...
bit complicated but very detailed ...
you are a professional ..
I would love to learn with you ...
great article ...

peninggi badan Indonesia

2/6/2010 1:52:54 AM #

send valentines cards

A really interesting blog, and  --as I'm a non techy girl --lots of funny gravatars. Useful Information, thanks to the author

send valentines cards United Kingdom

2/6/2010 11:59:45 PM #

abu dhabi property for sale

It was another joy to see your post. Really useful Post. You have complete command in your field, Great stuff as usual.

abu dhabi property for sale U.A.E.

2/7/2010 8:58:53 PM #

Life insurance

I’m impressed, you know what you’re talking about....

Life insurance United States

2/13/2010 7:13:18 AM #

designer rugs

great post thanks dear you are true blogger.

designer rugs United States

2/15/2010 11:18:58 AM #

Online SEO services

Great info.I like all your post.I will keep visiting this blog very often.It is good to see you verbalise from the heart and your clarity on this important subject can be easily observed..We Provide you the best Online SEO Services with high quality.

Online SEO services India

2/15/2010 11:34:46 AM #

designer rugs

wish I had found this blog before today. The advices in this posts are very helpful and I surely will read the other posts of this series too.Thank you for posting this. Your Blog is Bookmarked

designer rugs United States

2/18/2010 9:57:52 AM #

batu permata

I am flattered by your article
I hope we can exchange ideas and thoughts, so the best

batu permata Indonesia

3/2/2010 12:03:02 AM #

 betting odds

Hi,


Great blog ,thanks

betting odds United States

3/4/2010 9:40:25 PM #

alat kantor

very nice post Smile

alat kantor Indonesia

Add comment


(Will show your Gravatar icon)

  Country flag

Click to change captcha
biuquote
  • Comment
  • Preview
Loading