[ASP.NET] Horizontal Submenu from XML

In my last post I showed you a workaround that allowed you to create a horizontal submenu when you clicked on a MenuItem from another menu on the same page. That example hard-coded the MenuItem definitions into the code file, and I said that I’d be demonstrating how to create a horizontal submenu from a sitemap file. While attempting this, I got hit in the face by an error that has to do with hierarchy which I researched only to find that most people suggest it would be easier to find another alternative rather than try to solve the problem.

My alternative was to create a custom xml file that contains property definitions for the MenuItem class (namely Text and NavigateURL). Here it is:

<name>Visual Basic.NET</name>

1 <?xml version=1.0encoding=utf-8?>
2 <CategoriesMenu>
3 <item>
4 <id>0</id>
5 <name>VBScript</name>
6 <url>~/Articles/List.aspx?t=cat&amp;r=vbs</url>
7 </item>
8 <item>
9 <id>1</id>
11 <url>~/Articles/List.aspx?t=cat&amp;r=vbs</url>
12 </item>
13 <item>
14 <id>2</id>
15 <name>ASP.NET</name>
16 <url>~/Articles/List.aspx?t=cat&amp;r=vbs</url>
17 </item>
18 </CategoriesMenu>

Unfortunately, here’s where the frustration kicked in (mostly because I have very little experience working with XML). I had a lot of problems figuring out how to get the right values out of the XML and into my menu where I needed them. Good thing for you, I’ve spared you the aggravation by fighting through it for you.

Basically, we need to select each <name> and <url> element outlined in the XML and use the text inside of those as our menu definition properties. It took a few hours, but I managed it; here’s how:

<col style="width: 760px;” span=”1″>

1 Imports System.Xml
3 Protected Sub Menu1_ItemClick(ByVal sender As Object, ByVal e As System.WebUI.WebControls.MenuEventArgs) Handles Menu1.MenuItemClick

Select Case e.Item.Value.ToString


Case “Categories”


Dim doc As New XmlDocument




Dim NameNodes As XmlNodeList = doc.SelectNodes(“/CategoriesMenu/item/name”)


Dim URLNodes As XmlNodeList = doc.SelectNodes(“/CategoriesMenu/item/url”)


If NameNodes.Count = URLNodes.Count Then


For i As Integer = 0 To NameNodes.Count – 1


Dim m As New MenuItem


m.Text = NameNodes.Item(i).FirstChild.InnerText


m.NavigateUrl = URLNodes.Item(i).FirstChild.InnerText






End If


End Select

21 End Sub

What we’re doing here is opening the XML document that contains the defined structure for our menu (see XML sample above), and we’re selecting the XML Nodes in that document that match our XPath Expressions (namesly “/Categories/item/name”)
Once we have those collections, we need to check to make sure that both collections have the same amount of elements in them. We do this to avoid adding a menu item that doesn’t have a URL attached to it (which might happen if you get distracted while working on the XML).

If both collections have the same amount of elements, we know that the XML is valid (for our purposes at least), and we create a new menu item in our sub menu for each element in the collections.

All of this goes into a Select Case … End Select Statement to eliminate confusion in the case of multiple sub menus.

You could also use just the 1 XML file for all sub menus. Just replace the <CategoriesMenu></CategoriesMenu> element with the something else (<ProductsMenu></ProductsMenu> for instance). Remember, too, to add another Case to your select for the Products menu.

So, there you have it: A quick workaround to creating a horizontal submenu in asp.NET using XML as a data source.
It’s not as clean as it probably can be, but that’s what you get for teaching yourself code…

Until next time!



Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s