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)