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

Horizontal Submenu with Horizontal Menu using CSS Friendly Menu Control Adapter in C#

, 6 Oct 2010
Rate this:
Please Sign up or sign in to vote.
Rendering horizontal submenu with horizontal submenu by ASP.NET menu control using CSS friendly menu adapter from a scratch in .NET with C#

What Problem Does This Solution Solve?

By the built in ASP.NET 2.0 or 3.5 menu control is rendered as <table> elements that is difficult to manage by CSS and JavaScript. One can render the menu control output as <ul><li></ul> HTML elements instead of tables using CSS Menu Adapter Control that is easier to emit 100% pure CSS based rendering output.

In another words, for any Data list or in our case Menu Control, if you notice the HTML code by viewing the source of your page what ASP.NET runtime engine generates, you may see a Table based layout, which is of course really difficult to design and not considered a good practice in the new web standards. To overcome that issue, CSS Control Adapter is the answer. It will render div and unorderlist (UL) instead of table which can easily be redesigned using CSS. It means you can now have a standardized approach to create web based controls.

By this article, you can develop a horizontal menu with horizontal submenu from scratch using the ASP.NET menu control.

How Does This Help Someone Else?

Using this article, one can integrate CSS Control Adapter with Menu Control. A control adapter can help to produce CSS friendly HTML without sacrificing the power and flexibility of the original Menu control. For example, the root nodes(main menu) of the menu can be laid out vertically or horizontally and child nodes(sub menu) also can be laid out horizontally or vertically.

Background

There are a few articles on the web for rendering menu by CSS friendly menu adapter. Most of them are for vertical menu with vertical submenu or horizontal menu with vertical submenu. My concentration is horizontal menu with horizontal submenu.

Rendered Menu

Main menu.

MainMenu1.png

Screen-shot for hovering on brown colored tab.

SubmenuBrown1.png

Screen-shot for hovering on violet colored tab.

SubmenuViolet1.png

What is Going On Inside the Code Snippets?

My source code contained the solution summary as shown below:

SolutionSummary1.png

How Does the Code Actually Work?

The CSS Friendly Control Adapter overrides the default HTML generated by the ASP.NET Web controls to provide a more standards-based approach to presentation via CSS.
Control Adapters are classes (in our case MenuAdapter class ) that derive via the System.Web.UI.Adapters.ControlAdapter base class, and which implement rendering methods that allow a control adapter to completely customize how the markup of an individual control is rendered.

You can use these control adapter classes as-is to get pure CSS friendly output (no need to change the code), or you can tweak them if you want to customize the rendering output however you want.

ControlAdapters are then registered with ASP.NET by adding a .browser file to the /App_Browsers directory immediately underneath the project's application root. A .browser file includes simple markup like below that allows you to specify which Control Adapter should be used for which control.

<browsers>
  <browser refID="Default">
    <controlAdapters>
      <adapter controlType="System.Web.UI.WebControls.Menu"
               adapterType="CSSFriendly.MenuAdapter" />    
    </controlAdapters>
  </browser>
  <browser id="W3C_Validator" parentID="default">
    <identification>
      <userAgent match="^W3C_Validator" />
    </identification>
    <capabilities>
      <capability name="browser"              value="W3C Validator" />
      <capability name="ecmaScriptVersion"    value="1.2" />
      <capability name="javascript"           value="true" />
      <capability name="supportsCss"          value="true" />
      <capability name="supportsCallback"     value="true" />
      <capability name="tables"               value="true" />
      <capability name="tagWriter"            value="System.Web.UI.HtmlTextWriter" />
      <capability name="w3cdomversion"        value="1.0" />
    </capabilities>    
  </browser>
</browsers>

You can customize different control adapters for different browsers if you want, or just define them for "Default" to apply them by default to all browsers that visit your app.

Once you do that, you are good to go - and can use standard CSS stylesheets to customize all style information.

How To Add Your Menu Item

If you want to add a menu item with some submenu items by adding new node at your site map, you should only set menu style for your new class .AspNet-Menu-4-Left, .AspNet-Menu-4-Center, .AspNet-Menu-4-Right and submenu style for your new class AspNet-SubMenu-3 in MenuStyle.css.

/* AspNet-Menu-1 indicate its for root menu item 1,  
	AspNet-Menu-2 for root menu item 2 and so on */
/*Each root menu item has three parts Left, Center and Right */
.AspNet-Menu-1-Left { background:url(../Images/Menu/blueleft.png) no-repeat; 
	width:15px; float:left; height:31px;}
.AspNet-Menu-1-Center { background:url(../Images/Menu/bluemid.png) repeat-x; 
	width:146px; float:left; height:31px;}
.AspNet-Menu-1-Right { background:url(../Images/Menu/blueright.png) no-repeat; 
	width:15px; float:left; height:31px;}

.AspNet-Menu-2-Left { background:url(../Images/Menu/brownleft.png) no-repeat; 
	width:15px; float:left; height:31px;}
.AspNet-Menu-2-Center { background:url(../Images/Menu/brownmid.png) repeat-x; 
	width:146px; float:left; height:31px;}
.AspNet-Menu-2-Right { background:url(../Images/Menu/brownright.png) no-repeat; 
	width:15px; float:left; height:31px;}

.AspNet-Menu-3-Left { background:url(../Images/Menu/violetleft.png) no-repeat; 
	width:15px; float:left; height:31px;}
.AspNet-Menu-3-Center { background:url(../Images/Menu/violetmid.png) repeat-x; 
	width:146px; float:left; height:31px;}
.AspNet-Menu-3-Right { background:url(../Images/Menu/violetright.png) no-repeat; 
	width:15px; float:left; height:31px;}
/* AspNet-SubMenu-1 indicate its for submenu of 2nd menu ,  
	AspNet-Menu-2 for submenu of 3rd menu 
AspNet-Menu-3 for submenu of 4th menu and so on */
.AspNet-SubMenu-1{ position:absolute;left:0px; background-color :#c5b26f;}
.AspNet-SubMenu-2 { position:absolute; left:0px; background-color:#b188df;}		

Here AspNet-SubMenu-1 indicates it's for submenu of 2nd menu instead of 1st menu because 1st menu has no submenu items here.

Key CSS for Horizontal Submenu

Menu.css contains the following key CSS for horizontal submenu with horizontal menu.

/* -------------------------------------------------------------------------- */
/* When the Menu control's Orientation property is Horizontal the adapter 
/* wraps the menu with DIV */
/* whose class is AspNet-Menu-Horizontal. 
/* This allows us to force the top tier of the menu to layout */
/* horizontally, whereas all subsequent tiers of the menu lay out vertically. */

.AspNet-Menu-Horizontal ul.AspNet-Menu li
{
    float: left;
}

.AspNet-Menu-Horizontal ul.AspNet-Menu li li
{
    float: left;
}

Rendering <ul><li></ul> Elements

At MenuAdapter.cs, BuildItems method is responsible for dynamically rendering <ul><li></ul> elements based menu.

private void BuildItems(MenuItemCollection items, bool isRoot, HtmlTextWriter writer)
        {
            if (items.Count > 0)
            {
                writer.WriteLine();

                writer.WriteBeginTag("ul");
                if (isRoot)
                {
                    writer.WriteAttribute("class", "AspNet-Menu");
                }
                else
                {
                    writer.WriteAttribute("class", "AspNet-SubMenu-"+subMenuNo);
                    subMenuNo++;
                }
                 //subMenuNo=1 means, this is 1st SubMenu, 
                 //2 means this is 2nd Submenu and so on
                writer.Write(HtmlTextWriter.TagRightChar);
                writer.Indent++;
                int rootItemNo = 1;
                foreach (MenuItem item in items)
                {
                    if(items.Contains(firstMenuItem))
                        // rootItemNo=1 means, this is 1st rootItemNo, 
                        // 2 means this is 2nd rootItemNo, etc.
                        BuildItem(item, writer, true, rootItemNo); 
                    else
                        //Here IsRootItem=false so no need rootItemNo 
                        BuildItem(item, writer, false, 0); 
                    rootItemNo++;
                }

                writer.Indent--;
                writer.WriteLine();
                writer.WriteEndTag("ul");
            }
        }  

Enhanced ASP.NET 4.0 Menu Control

ASP.NET 4.0 makes things easier for web developers by providing “RenderingMode” properties. Here we can specify RenderMode of an ASP.NET Menu control which defines what will be the HTML Render Content Type. By default, the mode is “List” which means control will be rendered as ul/li.

See Abhijit Jana's technical Blog CSS Friendly Menu Control in ASP.NET 4.0.

Points of Interest

  • Cloud computing using Windows Azure and SQL Azure

License

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

About the Author

Shahdat Hosain
Software Developer
United States United States
I have 5 year+ experience on ASP.NET, ASP.NET Web API, MVC, C#, SQL Server 2005, 2008, E-commerce, , Windows Phone, LINQ2SQL, Entity Framework, LINQ2XML, ADO.NET, Telerik/RadControls, XHTML, XML, JavaScript, Jquery, Jquery Mobile, Ajax, HTML5 and CSS3.
I have significant knowledge on Java, JavaEE, EJB, JPA, JSF, Spring MVC, Hibernate, Design Pattern and problem domain analysis.
Follow on   Twitter   Google+   LinkedIn

Comments and Discussions

 
QuestionMouseover Tabs Menu. PinmemberMS Babu10-May-13 20:10 
Hello Shahdat,
 
Please help to convert 2 level asp menu like http://www.dynamicdrive.com/dynamicindex1/mouseovertabs.htm[^]
 
Thanks,
MS Babu
QuestionThree Level Horizontal Menu PinmemberMember 379239926-Feb-13 13:46 
AnswerRe: Three Level Horizontal Menu PinmemberShahdat Hosain26-Feb-13 17:40 
GeneralMy vote of 5 Pinmemberahmed rageeb5-Feb-13 10:08 
QuestionCustomizing Javascript or CSS for displaying Menus PinmemberMember 878315519-Jun-12 0:00 
GeneralMy vote of 5 PinmemberVitaly Tomilov10-Jun-12 5:00 
GeneralMy vote of 5 Pinmembermember6019-Apr-12 19:06 
QuestionQuestion Pinmemberlalaaa24-Feb-12 23:29 
AnswerRe: Question PinmemberShahdat Hosain1-Mar-12 20:17 
GeneralRe: Question Pinmemberlalaaa1-Mar-12 23:19 
QuestionDynamic Menus PinmemberJ walia5-Dec-11 21:26 
AnswerRe: Dynamic Menus PinmemberShahdat Hosain6-Dec-11 19:22 
QuestionWant to change onclick instead of hover PinmemberChinmaya858-Nov-11 23:02 
QuestionIn Master page Pinmemberdvv_vishnu12-Jul-11 19:24 
GeneralMy vote of 5 Pinmembertmbeniamin5-May-11 21:34 
GeneralSpacing between sub-menu items PinmemberHoodwink130-Mar-11 10:30 
GeneralDynamically selecting menu items PinmemberErich Singer28-Mar-11 10:18 
GeneralRe: Dynamically selecting menu items PinmemberHoodwink130-Mar-11 5:37 
GeneralChanging Height of submenu PinmemberMember 232529325-Jan-11 21:57 
GeneralRe: Changing Height of submenu PinmemberMember 232529326-Jan-11 1:35 
GeneralHi, Pinmemberdazy12110-Jan-11 1:04 
GeneralRe: Hi, PinmemberShahdat Hosain24-Jan-11 16:44 
Generalthank you for the great code, i have a question however PinmemberconduitMember22-Nov-10 0:15 
GeneralRe: thank you for the great code, i have a question however [modified] PinmemberShahdat Hosain5-Dec-10 22:59 
GeneralMy vote of 5 Pinmemberdider712-Nov-10 7:26 

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
Web01 | 2.8.140709.1 | Last Updated 6 Oct 2010
Article Copyright 2010 by Shahdat Hosain
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid