Click here to Skip to main content
15,881,803 members
Articles / Web Development / CSS
Article

ASP.NET Menu Parent Menuitem Highlighting

Rate me:
Please Sign up or sign in to vote.
4.78/5 (17 votes)
17 Jan 2008CPOL3 min read 162.5K   3.8K   71   11
A work-around for ASP.NET menu parent menuitem highlighting.

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:

C#
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:

C#
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.

C#
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.

JavaScript
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)


Written By
Software Developer Epam Systems
Hungary Hungary
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questionwhat type is the mainMenu ? Pin
Member 1466431321-Nov-19 18:11
Member 1466431321-Nov-19 18:11 
QuestionMenu highlight not working with Master page Pin
Member 442666531-Aug-12 3:23
Member 442666531-Aug-12 3:23 
QuestionIE8 &IE6 Pin
Member 27334338-Oct-11 5:18
Member 27334338-Oct-11 5:18 
QuestionQuestion on the menu background colors Pin
Dannoman123418-Feb-11 4:56
Dannoman123418-Feb-11 4:56 
GeneralMy vote of 4 Pin
technicaldoubts11-Nov-10 22:33
technicaldoubts11-Nov-10 22:33 
Pretty good article, helped a lot to solve my issue...
GeneralOpera 9.80 Pin
test05110214-Oct-09 23:51
test05110214-Oct-09 23:51 
Generalhighlighting the text in the datalist item command Pin
mohanreddy0428-Jul-08 19:33
mohanreddy0428-Jul-08 19:33 
QuestionCan it be done without script manager Pin
Manisha21083-Jun-08 23:24
Manisha21083-Jun-08 23:24 
GeneralSiteMap & Master Page Pin
William Hindman16-Mar-08 8:01
William Hindman16-Mar-08 8:01 
GeneralNice Pin
Norberto Olazabal8-Feb-08 5:41
Norberto Olazabal8-Feb-08 5:41 
GeneralRe: Nice Pin
Rolf Szomor12-Feb-08 22:44
Rolf Szomor12-Feb-08 22:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.