Click here to Skip to main content
6,595,444 members and growing! (18,217 online)
Email Password   helpLost your password?
Web Development » ASP.NET Controls » Menu Controls     Intermediate License: The Code Project Open License (CPOL)

ASP.NET Menu Parent Menuitem Highlighting

By Rolf Szomor

A work-around for ASP.NET menu parent menuitem highlighting.
C# (C# 1.0, C# 2.0, C# 3.0), Javascript, CSS, HTML, Windows (Win2K, WinXP, Win2003, Vista), .NET (.NET 2.0, .NET 3.5), ASP.NET, IIS (IIS 5.1, IIS 6, IIS 7), Visual Studio (VS2005, VS2008), Ajax, Dev, Design
Posted:17 Jan 2008
Updated:17 Jan 2008
Views:41,174
Bookmarked:56 times
Announcements
Loading...
 
Search    
Advanced Search
Add to IE Search
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
12 votes for this article.
Popularity: 4.50 Rating: 4.17 out of 5

1
3 votes, 25.0%
2

3
1 vote, 8.3%
4
8 votes, 66.7%
5

sample.png

Introduction

This is a simple workaround for the ASP.NET 2.0 menu control's parent menu item highlighting.

Background

I have some websites which have relatively big and deep menu structures. If the user scrolls deep with the mouse in ASP.NET menus, after some levels, the look of the menu becomes a little too complex, and maybe the user would be be confused as to which are the parents of the current menuitem?

There is a solution called CSS Friendly Adapters. I tried to use this, but I think it is full of bugs, and its behavior is often very crazy and annoying. There are a lot of differences between the original ASP.NET menu control and the ASP.NET menu with CSS Friendly Adapters, and I did not like that...

Using the Code

First of all, this is not the most beautiful solution, but it works. First, I wanted to do everything on the server side, but I found that the MenuItem does not inherit from Control, and because of that, it does not have client side attributes which can be manipulated. Thus, I decided to look what client-side code the ASP.NET menu generates. I noticed that it is a big table, and some of the rows have ID attributes, which begin with the ClientID of the ASP.NET menu, and OnMouseOver and OnMouseOut event handlers. I played a little with the event handlers, and figured out that if I call them explicitly from JavaScript, I can highlight any of the menu items.

Thus, I just needed to find out how the ASP.NET menu generates client IDs. This is very simple. If you search on the server side for the menu items recursively, you just need to number them with a simple counter, and you will get the generated client side number of the menu items. Here is the code, which searches for the menu items:

void FindMenuItems(MenuItem mi, List<MenuItem> list)
{
    foreach (MenuItem child in mi.ChildItems)
    {
        list.Add(child);
    }

    foreach (MenuItem child in mi.ChildItems)
    {
        FindMenuItems(child, list);
    }
}

We have the menu items, now we need to iterate through the list, and find all the parents (to the root) for every menu item.

Here is the code which searches the parents of a menu item:

void FindParents(MenuItem mi, List<MenuItem> list)
{
    if(mi.Parent != null)
    {
        if(mi.Parent != mainMenu.Items[0])
        {
            list.Add(mi.Parent);
            FindParents(mi.Parent, list);
        }
    }
}

Putting It All Together

In the Page_Load event handler, I call the above methods for every menu item. I find every parent (till the root), and calculate the client side ID of both the current menu item and the parent menu items. I concatenate the parent menu item's client side IDs to one comma separated string. And finally, I bind a client side OnMouseOver and OnMouseOut event handler for each menu item. To these event handlers, I pass two parameters: the menu item's client side ID, and the comma separated string, which holds the menu item's parents.

List<MenuItem> list = new List<MenuItem>();
list.Add(mainMenu.Items[0]);
FindMenuItems(mainMenu.Items[0], list);

foreach (MenuItem mi in list)
{
    List<MenuItem> parents = new List<MenuItem>();
    FindParents(mi, parents);
    string parentSnake = String.Empty;




    foreach (MenuItem parent in parents)
    {
        parentSnake += "mainMenun" + list.IndexOf(parent).ToString() + ",";
    }

    parentSnake.TrimEnd(',');

    script += "document.getElementById(
        '" + mainMenu.ClientID + "n" + 
        list.IndexOf(mi).ToString() + "').onmouseover = 
        function(){HoverParents('" + mainMenu.ClientID + 
        "n" + list.IndexOf(mi).ToString() + "', '" + parentSnake + "')};";
    script += "document.getElementById('" + mainMenu.ClientID + "n" + 
        list.IndexOf(mi).ToString() + 
        "').onmouseout = function(){UnhoverParents('" + 
        mainMenu.ClientID + "n" + list.IndexOf(mi).ToString() + "', '" + 
        parentSnake + "')};";

}

ScriptManager.RegisterStartupScript(this, typeof(string), 
    "MenuHoverUnhover", script, true);

The event handlers are written in JavaScript. The OnMouseOver highlights the actual menu item, just like the original ASP.NET generated code does (with the same method call), after that iterates through the parents comma separated list and highlights them all the same way. The OnMouseOut does the opposite of that.

function HoverParents(id, parentSnake)
{
    Menu_HoverDynamic(document.getElementById(id));
    var parents = parentSnake.toString().split(',');

    for(i = 0;i < parents.length;i++)
    {
        if(parents[i] != '')
        {
            Menu_HoverDynamic(document.getElementById(parents[i]));
        }
    }
}

function UnhoverParents(id, parentSnake)
{ 
    Menu_Unhover(document.getElementById(id));
    var parents = parentSnake.toString().split(',');

    for(i = 0;i < parents.length;i++)
    {
        if(parents[i] != '')
        {
            Menu_Unhover(document.getElementById(parents[i]));
        }
    }
}

Once we get the client-side script which binds the event handlers, I use the Script Manager to embed the JavaScript in the page at every postback.

Points of Interest

Relying on client-side generated IDs is not the best method you can choose, but sometimes, it is simple, and works fine.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Rolf Szomor


Member

Occupation: Software Developer
Company: Epam Systems
Location: Hungary Hungary

Other popular ASP.NET Controls articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 7 of 7 (Total in Forum: 7) (Refresh)FirstPrevNext
GeneralOpera 9.80 Pinmembertest0511020:51 15 Oct '09  
QuestionNo pop-ups PinmemberLMRT0911:23 4 Sep '09  
Generalhighlighting the text in the datalist item command Pinmembermohanreddy0420:33 28 Jul '08  
GeneralCan it be done without script manager PinmemberManisha21080:24 4 Jun '08  
GeneralSiteMap & Master Page PinmemberWilliam Hindman9:01 16 Mar '08  
GeneralNice PinmemberNorberto Olazabal6:41 8 Feb '08  
GeneralRe: Nice PinmemberRolf Szomor23:44 12 Feb '08  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 17 Jan 2008
Editor: Smitha Vijayan
Copyright 2008 by Rolf Szomor
Everything else Copyright © CodeProject, 1999-2009
Web17 | Advertise on the Code Project