An Xml-Driven, Self-Caching ASCX MenuStrip Control

Peter reveals his latest creation - a self-caching ASCX Menustrip Control.

If you are like me, you are always looking for ways to make your programming life easier - reusable class libraries and controls being a prime target of this effort. One of the things that annoys me about ASP.NET 2.0 is that it offers an ASP.NET menu control, but I just can't bring myself to like it. Sure, it's highly configurable, works with SiteMap xml data, and so on. But, regardless of the amount of tinkering I"ve done, there always seems to be some little annoyance about it's behavior that "gets my goat".

For the kind of development I do, I rarely need one of those fancy-schmancy multilevel javascript callback xpealidocious bodacious scriptabobulous menu thingies. All I need is what I like to call a "MenuStrip". Its a control that lays out items that link to to where you want to go, and it fits with the CSS and design of your page. I don't need dropdowns because if you click an item, you go to that page where I would have another one of these with page-specific items on it, including a "HOME" item that can take you back to the home page (or to where you came from). You can drag the control into a ContentPlaceholder on your page, set an XML source file for the menu items, and you are done.

What I"ve done here, since I couldn't find one already done - that I liked, is to create such an animal, with these features:

1) The CSS to match my page layout is inline in the ASCX page portion of the control. It's not a lot of CSS, so I'd rather have it "keep it's own". If I ever need to change it for another site, that's easy to do.

2) The control loads the XML to display its contents into a DataSet, and caches it for speed. It also sports a file-based CacheDependency so that if I want to change the items on a particular menu, all I need to do is edit the small Xml File that specifies them. When the file is changed, the Cache Item gets invalidated and the control automatically reloads the modified file, updating my changes instantly.

3) You can specify the name of the Xml file to use as a property of the control - so each MenuStrip on each page knows exactly which Xml file to use for the items it is supposed to display.

Here's an example of what one looks like, minus the page, and I also have a separate page where you can look at images of two different versions:

Example ASCX Menustrip Control

Here's a link to the bigger pictures.

When you download this solution, I'm going to include a MasterPage and two Default pages with two different versions of the control on them, so everything will integrate nicely in a nice site layout. The original CSS Layout came from a free template for SNews, a PHP CMS application; I've converted it to a nice MasterPage.

Now let's look at the code for the ASCX codebehind:

    1 using System;

    2 using System.Data;

    3 using System.Configuration;

    4 using System.Collections;

    5 using System.Web;

    6 using System.Web.Security;

    7 using System.Web.UI;

    8 using System.Web.UI.WebControls;

    9 using System.Web.UI.WebControls.WebParts;

   10 using System.Web.UI.HtmlControls;

   11 using System.Data.SqlClient;

   12 

   13 namespace MenuStrip

   14 {

   15     public partial class ucMenu : System.Web.UI.UserControl

   16     {

   17         private string menuFile = "Menu.xml";

   18 

   19         public string MenuFile

   20         {

   21             get { return menuFile; }

   22             set { menuFile = value; }

   23         }

   24 

   25         protected void Page_Load(object sender, EventArgs e)

   26         {

   27             PopulateMenu();

   28         }

   29 

   30 

   31             private void PopulateMenu()

   32             {

   33                 DataSet ds=new DataSet();

   34                 if (Cache[menuFile] != null)

   35                 {

   36                     ds = (DataSet)Cache[menuFile];

   37                 }

   38                 else

   39                 {

   40                     ds.ReadXml(Server.MapPath(menuFile));

   41                     Cache.Insert(menuFile,ds, new

   42   System.Web.Caching.CacheDependency(Server.MapPath(menuFile)));

   43 

   44                 }

   45                     DataTable dt = ds.Tables[0];

   46                 HyperLink hl = null;

   47                 string ctrlId = "";

   48                 for (int i = 0; i < dt.Rows.Count; i++)

   49                 {

   50                     ctrlId = "HyperLink" + i.ToString();

   51                     hl = (HyperLink)this.FindControl(ctrlId);

   52                     hl.NavigateUrl = (string)dt.Rows[i]["NavigateUrl"];

   53                     hl.Text = (string)dt.Rows[i]["Text"];

   54                 }               

   55            }

   56     }

   57 }

You see that the Menustrip control has a public MenuFile property which allows us to specify the Xml File in the declarative markup for the control, like so:

<uc1:ucMenu ID="UcMenu1" runat="server" MenuFile="Menu.Xml" />

Then, I have the control load the required file into a DataSet, Cache it and set a file-based CacheDependency, and it proceeds to "fill in" the NavigateUrl and Text Properties of a bunch of blank Hyperlink Controls that I have in the HTML Markup portion of the ASCX "Page". The rest is done via CSS. You can have as many "blank" Hyperlink controls in the HTML markup of the ASCX as you think you may have menu-items, controls that aren't populated by the code simply don't show up.

This may be a little different approach than other "menu" thingies that you have seen, I hope you like it. The solution you can download below has two fully working versions of the control, and the items point to actual pages on eggheadcafe.com (we'd like you to stick around while you are experimenting with it).

One last item - this is a WAP (Web Application Project) NOT a "WebSite" project. If you haven't installed the WAP add-in, you will find that the solution does not load. You can find out more about WAP along with a link to the download at ScottGu's Blog here.

Download the Visual Studio 2005 Web Application Project Solution that acompanies this article

By Peter Bromberg   Popularity  (2652 Views)