Home   Blog   Contact  |  Admin

Custom Menu Control

Menus are an essential part of any website. Asp .NET comes with a great menu control, but it’s really only suitable for a static menu structure. As soon as I started developing this site, I found the need for a dynamic menu control which could be placed in all my pages, and show the relevant/suitable links. The data is based on a simple XML file with a structure instinctive of any common sitemap.

To start with let's get your XML file sorted out. Each page is identified with an article node, each having a title and url attribute. The file starts with a single root node, which doesn't require a url if neccessary. This file demonstrates the structure.

articles.xml <?xml version="1.0" encoding="utf-8" ?> <article title="Asp.NET Tutorials" url="Default.aspx"> <article title="XML In Asp.NET" url="XML.aspx"> <article title="Writing A New XML File" url="WritingXMLFile.aspx"/> <article title="Reading An XML File" url="ReadingXML.aspx" /> <article title="Editing An XML File" url="EditingXML.aspx" /> </article> <article title="Controls" url="Controls.aspx"> <article title ="Custom Menu" url="CustomMenu.aspx" /> </article> </article>

The menu will display links to all the sibling pages of the current page, and the parent page. Every page that will use the menu control should be in the XML file, otherwise the root node will be displayed. The display of the menu is very flexible, as its simply a Literal control filled with HTML when the menu is loaded. In its current form, the parent page link is displayed in a <h2> tag, and sibling page links in an unordered list, as in the demonstration below.

Now lets take a look at the code which is executed in the Page_Init sub. This is fairly simple, first find the filename of the current page, so we know what page we're looking for in the articles file. Dim page As String = Request.FilePath page = page.Substring(page.LastIndexOf("/") + 1)

Next load the articles file. Dim articles As New XmlDocument articles.Load(Server.MapPath("~/aspnet/articles.xml"))

Look in the file for the links that need to be shown. This is done in a seperate function called FindLinks which will be looked at later. Dim links As XmlNode = FindLinks(page, articles.DocumentElement) If links Is Nothing Then 'Couldn't find current page links = articles.DocumentElement 'Use root element End If

Generate some HTML to display. ltrLinks.Text = "<h2><a href='" & links.Attributes("url").Value & "'>" & links.Attributes("title").Value & "</a></h2>" If links.HasChildNodes Then ltrLinks.Text &= "<ul>" For Each child As XmlNode In links.ChildNodes ltrLinks.Text &= "<li><a href='" & child.Attributes("url").Value & "'>" & child.Attributes("title").Value & "</a></li>" Next ltrLinks.Text &= "</ul>" End If

Lets have a quick look at the FindLinks function. It is used to find the links which need to be displayed. The function returns an XmlNode, which has attributes describing the parent page, and child nodes for each sibling page. Private Function FindLinks(ByVal page As String, ByRef xml As XmlNode) As XmlNode If xml.HasChildNodes Then For Each child As XmlNode In xml.ChildNodes If child.Attributes("url").Value = page Then Return xml Else Dim res As XmlNode = FindLinks(page, child) If Not res Is Nothing Then Return res End If End If Next Return Nothing 'page not found in xml Else Return Nothing 'Nowhere to look for page End If End Function

Limitations

In its current form, the menu control requires that all pages are in the same folder, with the article's XML file. The data file must also use each pages filename as its url attribute. This could easily be changed to allow subfolders, with a few changes to the code. Firstly, the url attribute in the data file would have to include any subfolders (eg. url="subfolder1/page1.aspx"). Then, instead of the code simply getting the current pages filename, it would need to be the page's path from the root folder. And finally, the HTML links which are generated would need to be changed to deal with subfolders.

If you have any bugs to report, or improvements to suggest, feel free to email me.

Download

CustomMenuControl.zip (1.23kB)