Click here to Skip to main content
15,879,535 members
Articles / Web Development / CSS

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

Rate me:
Please Sign up or sign in to vote.
4.81/5 (51 votes)
27 Jun 2016CPOL4 min read 211.8K   6.9K   81   41
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.

HorizontalSubmenu/MainMenu1.png

Screen-shot for hovering on brown colored tab.

HorizontalSubmenu/SubmenuBrown1.png

Screen-shot for hovering on violet colored tab.

HorizontalSubmenu/SubmenuViolet1.png

What is Going On Inside the Code Snippets?

My source code contained the solution summary as shown below:

HorizontalSubmenu/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.

XML
<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.

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;}
CSS
/* 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.

CSS
/* -------------------------------------------------------------------------- */
/* 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.

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

License

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


Written By
Software Developer (Senior)
United States United States
I have 5 year+ experience on ASP.NET, ASP.NET Web API, MVC, C#, SQL Server 2005, 2008, NopCommerce, 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.

Comments and Discussions

 
Questionvertical sub-menus Pin
Echeban18-Sep-17 8:21
Echeban18-Sep-17 8:21 
QuestionMouseover Tabs Menu. Pin
MS Babu10-May-13 20:10
MS Babu10-May-13 20:10 
QuestionThree Level Horizontal Menu Pin
Member 379239926-Feb-13 13:46
Member 379239926-Feb-13 13:46 
AnswerRe: Three Level Horizontal Menu Pin
Shahdat Hosain26-Feb-13 17:40
Shahdat Hosain26-Feb-13 17:40 
GeneralMy vote of 5 Pin
ahmed rageeb5-Feb-13 10:08
ahmed rageeb5-Feb-13 10:08 
QuestionCustomizing Javascript or CSS for displaying Menus Pin
Member 878315519-Jun-12 0:00
Member 878315519-Jun-12 0:00 
GeneralMy vote of 5 Pin
Vitaly Tomilov10-Jun-12 5:00
Vitaly Tomilov10-Jun-12 5:00 
GeneralMy vote of 5 Pin
member6019-Apr-12 19:06
member6019-Apr-12 19:06 
QuestionQuestion Pin
lalaaa24-Feb-12 23:29
lalaaa24-Feb-12 23:29 
AnswerRe: Question Pin
Shahdat Hosain1-Mar-12 20:17
Shahdat Hosain1-Mar-12 20:17 
GeneralRe: Question Pin
lalaaa1-Mar-12 23:19
lalaaa1-Mar-12 23:19 
QuestionDynamic Menus Pin
Jagz W5-Dec-11 21:26
professionalJagz W5-Dec-11 21:26 
I am binding menu control with database table because i don't have predefined menu. My client wants to change when ever he wants. so how this be achieved?

One person's data is another person's program.

--J.Walia
AnswerRe: Dynamic Menus Pin
Shahdat Hosain6-Dec-11 19:22
Shahdat Hosain6-Dec-11 19:22 
QuestionWant to change onclick instead of hover Pin
Chinmaya858-Nov-11 23:02
Chinmaya858-Nov-11 23:02 
QuestionIn Master page Pin
dvv_vishnu12-Jul-11 19:24
dvv_vishnu12-Jul-11 19:24 
GeneralMy vote of 5 Pin
tmbeniamin5-May-11 21:34
tmbeniamin5-May-11 21:34 
GeneralSpacing between sub-menu items Pin
Hoodwink130-Mar-11 10:30
Hoodwink130-Mar-11 10:30 
GeneralDynamically selecting menu items Pin
Erich Singer28-Mar-11 10:18
professionalErich Singer28-Mar-11 10:18 
GeneralRe: Dynamically selecting menu items Pin
Hoodwink130-Mar-11 5:37
Hoodwink130-Mar-11 5:37 
GeneralChanging Height of submenu Pin
Member 232529325-Jan-11 21:57
Member 232529325-Jan-11 21:57 
GeneralRe: Changing Height of submenu Pin
Member 232529326-Jan-11 1:35
Member 232529326-Jan-11 1:35 
GeneralHi, Pin
dazy12110-Jan-11 1:04
dazy12110-Jan-11 1:04 
GeneralRe: Hi, Pin
Shahdat Hosain24-Jan-11 16:44
Shahdat Hosain24-Jan-11 16:44 
Generalthank you for the great code, i have a question however Pin
conduitMember22-Nov-10 0:15
conduitMember22-Nov-10 0:15 
GeneralRe: thank you for the great code, i have a question however [modified] Pin
Shahdat Hosain5-Dec-10 22:59
Shahdat Hosain5-Dec-10 22:59 

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.