Programmatic Menus: Optimize Your Menus in Code-behind

In this article, I want to show how you can setup your menus in code-behind and avoid redundancy. I recently inherited a web application with the menu system setup in the code-in-front. Each menu shared identical values, other than the visibility. Notice that numerous properties are defined more than once, above and below the MenuItems. What's as bad is that this entire block of code was repeated for 6 additional menus.

Example of Redundant, Bloated Menu Setup

<asp:Menu StaticMenuItemStyle-Font-Bold="true" Visible="true" 
    StaticMenuItemStyle-ForeColor="white"
    StaticMenuStyle-HorizontalPadding="4" 
StaticMenuItemStyle-Font-Names="verdana" DynamicMenuItemStyle-Font-Names="verdana"
DynamicMenuItemStyle-Font-Size="Smaller" StaticMenuItemStyle-Font-Size="Small" BorderColor="darkblue"
BorderWidth="1" DynamicMenuItemStyle-BorderWidth="2"
DynamicMenuItemStyle-BorderColor="#CCCCCC" DynamicHoverStyle-BackColor="wheat"
DynamicHoverStyle-ForeColor="black" DynamicHoverStyle-Font-Bold="true" DynamicMenuItemStyle-VerticalPadding="4"
DynamicMenuItemStyle-HorizontalPadding="4" DynamicSelectedStyle-BorderStyle="None"
ID="Menu1" runat="server" Font-Underline="False" Width="90px"> <Items> <asp:MenuItem>...</asp:MenuItem> </Items> <StaticMenuItemStyle Font-Underline="False"
Font-Bold="True" Font-Names="verdana" Font-Size="Small" ForeColor="White" /> <DynamicMenuStyle BackColor="#F2F8FF"
BorderColor="LightSkyBlue" BorderStyle="Solid" BorderWidth="1px" /> <DynamicMenuItemStyle Font-Underline="False"
BorderColor="#CCCCCC" BorderWidth="2px" Font-Names="verdana" Font-Size="Smaller"
HorizontalPadding="4px" VerticalPadding="4px" /> <StaticMenuStyle HorizontalPadding="4px" /> <DynamicHoverStyle BackColor="Wheat"
Font-Bold="True" ForeColor="Black" /> <DynamicSelectedStyle BorderStyle="None" /> </asp:Menu>

If a property needs changed, the programmer must make certain that the change is made in all six instances of this block of code, for each menu, as well as realizing that certain properties are defined twice. This type of coding can introduce problems after updates and edits.

To optimize this menu, let's move this to the code-behind so that if a change is needed, it is only needed in one line of code. In our code-in-front, we'll simply setup the menus like so:

Streamlined Menu

<asp:Menu ID="Menu1" runat="server">
    <Items>
        <asp:MenuItem>...</asp:MenuItem>
    </Items>
</asp:Menu>
<asp:Menu ID="Menu2" runat="server">
    <Items>
        <asp:MenuItem>...</asp:MenuItem>
    </Items>
</asp:Menu>
...and so forth


In our codebehind, we'll setup each menu in our Page_Load and define one function that will set the properties for each menu:

Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load MenuSetup(Menu1, True) MenuSetup(Menu2, True) MenuSetup(Menu3, True) MenuSetup(Menu4, False) MenuSetup(Menu5, False) MenuSetup(Menu6, False) End Sub

Remember I said that the only difference in these menus was the visibility? So in our MenuSetup function we'll pass in the menu ID, as well as whether the menu should be visible or not. I've altered some of the values from what you see in the original code-in-front, but you get the idea. Be sure to import System.Drawing for the colors.

Protected Sub MenuSetup(ByVal myMenu As Menu, _
ByVal visibility As Boolean) myMenu.Visible = visibility myMenu.BorderColor = Drawing.Color.Black myMenu.BorderWidth = Unit.Pixel(1) myMenu.Font.Underline = False myMenu.Width = Unit.Pixel(90) myMenu.StaticMenuStyle.HorizontalPadding = Unit.Pixel(4) myMenu.StaticMenuItemStyle.Font.Bold = True myMenu.StaticMenuItemStyle.Font.Name = "Verdana" myMenu.StaticMenuItemStyle.Font.Size = "10" myMenu.StaticMenuItemStyle.Font.Underline = False myMenu.StaticMenuItemStyle.ForeColor = Color.White myMenu.DynamicMenuStyle.BorderWidth = Unit.Pixel(1) myMenu.DynamicMenuItemStyle.Font.Bold = True myMenu.DynamicMenuItemStyle.Font.Name = "Verdana" myMenu.DynamicMenuItemStyle.Font.Size = "8" myMenu.DynamicMenuItemStyle.BorderWidth = Unit.Pixel(1) myMenu.DynamicMenuItemStyle.BorderColor = _
ColorTranslator.FromHtml("#CCCCCC") myMenu.DynamicMenuItemStyle.BorderStyle = BorderStyle.None myMenu.DynamicMenuItemStyle.VerticalPadding = Unit.Pixel(4) myMenu.DynamicMenuItemStyle.HorizontalPadding = Unit.Pixel(4) myMenu.DynamicMenuItemStyle.ForeColor = Color.Black myMenu.DynamicMenuItemStyle.BackColor = _
ColorTranslator.FromHtml("#F0F2F4") myMenu.DynamicHoverStyle.BackColor = _
ColorTranslator.FromHtml("#CCCCCC") myMenu.DynamicHoverStyle.ForeColor = _
ColorTranslator.FromHtml("#00008B") myMenu.DynamicSelectedStyle.ForeColor = _
ColorTranslator.FromHtml("#00008B") End Sub

Notice some of the differences when defining properties in the code-behind:

Front Behind
Imports System.Drawing ' for Colors
Width="90px" myMenu.Width = Unit.Pixel(90)
StaticMenuItemStyle-Font-Bold="true" myMenu.StaticMenuItemStyle.Font.Bold = True
Visible="true" myMenu.Visible = visibility
StaticMenuStyle-HorizontalPadding="4" myMenu.StaticMenuStyle.HorizontalPadding = Unit.Pixel(4)
StaticMenuItemStyle-Font-Names="verdana" myMenu.StaticMenuItemStyle.Font.Name = "Verdana"
(singular .Name for one)
StaticMenuItemStyle-Font-Size="Small" myMenu.StaticMenuItemStyle.Font.Size = "10"
DynamicMenuItemStyle-BorderWidth="2" myMenu.DynamicMenuItemStyle.BorderWidth = Unit.Pixel(2)
DynamicMenuItemStyle-BorderColor="#CCCCCC" myMenu.DynamicMenuItemStyle.BorderColor = ColorTranslator.FromHtml("#CCCCCC")
DynamicHoverStyle-BackColor="wheat" myMenu.DynamicMenuItemStyle.BackColor = Color.Wheat
DynamicHoverStyle-Font-Bold="true" myMenu.DynamicHoverStyle.Font.Bold = True
DynamicSelectedStyle-BorderStyle="None" myMenu.DynamicSelectedStyle.BorderStyle = BorderStyle.None

May your dreams be in ASP.NET!

Nannette Thacker

6 Comments

  • Alternatively you can use Skins if you are using ASP.NET 2.0 and above. This way you can define a skin with all the common properties and behaviour of the menu.

  • It might be better to put the various styles in CSS classes...you could use the visual CSS tools to design the menus look and feel.

    And then apply the styles programmatically as you have done.

  • It seems that putting the menu into a control would be a possible workround, but the proper fix would be to use a css class and an external css.

  • Another great usage of styling your menus programmatically, is if you have a dynamic menu module where the menu items are stored in a database. Perhaps you can customize which class, or size or styles, etc. are defined on a menu by menu basis within your tables.

    Then when building your menuing system, you could traverse the table and populate the properties at that time.

    But yes, using a CSS style is a great idea, as well as using a skin. My goal here was to show how to programmatically setup the menu.

    thanks!

  • I came across this while searching for a way to hide certain menus using an ASP.NET Menu Control.

    This is beautiful, it was exactly was I was looking for.

    Thanks for sharing!

  • Peter,

    I'd recommend you use a VB to C# converter. Here are two:

    http://converter.telerik.com/

    http://www.developerfusion.com/tools/convert/vb-to-csharp/

    This will be a lifesaver for future snippets you want to convert. I use it all the time.

    Nannette

Comments have been disabled for this content.