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