Click here to Skip to main content
Click here to Skip to main content

ASP.NET Menu Parent Menuitem Highlighting

, 17 Jan 2008
Rate this:
Please Sign up or sign in to vote.
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:

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)

Share

About the Author

Rolf Szomor
Software Developer Epam Systems
Hungary Hungary
No Biography provided

Comments and Discussions

 
QuestionMenu highlight not working with Master page PinmemberMember 442666531-Aug-12 3:23 
QuestionIE8 &IE6 PinmemberMember 27334338-Oct-11 5:18 
QuestionQuestion on the menu background colors PinmemberMember 455521618-Feb-11 4:56 
GeneralMy vote of 4 Pinmembertechnicaldoubts11-Nov-10 22:33 
GeneralOpera 9.80 Pinmembertest05110214-Oct-09 23:51 
Generalhighlighting the text in the datalist item command Pinmembermohanreddy0428-Jul-08 19:33 
QuestionCan it be done without script manager PinmemberManisha21083-Jun-08 23:24 
GeneralSiteMap & Master Page PinmemberWilliam Hindman16-Mar-08 8:01 
GeneralNice PinmemberNorberto Olazabal8-Feb-08 5:41 
GeneralRe: Nice PinmemberRolf Szomor12-Feb-08 22:44 

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

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

| Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 17 Jan 2008
Article Copyright 2008 by Rolf Szomor
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid