I'm trying to build a vertical, static ASP Menu from the SiteMap file in which the child items for a node only display if they or their parent node are currently selected. For instance, say my SiteMap is:
Item1
Item2
- Child2.1
- Child2.2
Item3
- Child3.1
- Child3.2
On the home page (Item1), I want my static menu to appear as:
Item1
Item2
Item3
Were I on the Item2 or Child2.1 page, I want my static menu to appear as:
Item1
Item2
- Child2.1
- Child2.2
Item3
I'm trying to do this programmatically in the MasterPage during Menu_DataBound, but so far have failed. As the main navigation of my site already employs dynamic menus, I do not wish to employ them on this second-tier navigation.
In lieu of using the asp:Menu, I've tried building out the code in a Label:
Protected Sub LeftNavMenu_DataBound(sender As Object, e As System.EventArgs) Handles
LeftNavMenu.DataBound
If LeftNavMenu.Items.Count > 0 Then
Dim item As MenuItem
For Each item In LeftNavMenu.Items
DisplayChildMenuText(item)
Next
Else
lblNav.Text = "The Menu control does not have any items."
End If
End Sub
Sub DisplayChildMenuText(ByVal item As MenuItem)
If item.Selected Then
lblNav.Text &= "<li><span class=""active""></span><a href=""" & item.NavigateUrl & """>" & item.Text & "</a></li>"
If item.ChildItems.Count > 0 Then
Dim childItem As MenuItem
lblNav.Text &= "<ul>"
For Each childItem In item.ChildItems
lblNav.Text &= "<li><a href=""" & childItem.NavigateUrl & """>" & childItem.Text & "</a></li>"
Next
lblNav.Text &= "</ul>"
End If
Else
lblNav.Text &= "<li><a href=""" & item.NavigateUrl & """>" & item.Text & "</a></li>"
End If
End Sub
This displays the correct navigation if I'm on the top-tier links (Item2, Item3), but fails if I select a child page.
I sincerely apologize if this has been answered elsewhere. This seems like a fairly rudimentary request and something that should be built into ASP Menus, however I've tried for weeks to find a solution. Granted I may just be searching for the wrong keywords.
Figured it out. Sharing for the greater good. This evaluates each item in the menu during the MenuItemDataBound event, checks if the item is a child, checks if it's in an active node and, if it's not, removes it.
<script runat="server">
Protected Sub Menu1_MenuItemDataBound(sender As Object, e As System.Web.UI.WebControls.MenuEventArgs) Handles Menu1.MenuItemDataBound
If e.Item.Parent IsNot Nothing Then
If e.Item.Parent.Text <> SiteMap.CurrentNode.Title And e.Item.Parent.Text <> SiteMap.CurrentNode.ParentNode.Title Then
e.Item.Parent.ChildItems.Remove(e.Item)
End If
End If
End Sub
</script>
Be sure your menu is set up to display two StaticDisplayLevels, e.g.:
<asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource1" IncludeStyleBlock="False"
MaximumDynamicDisplayLevels="0" SkipLinkText="" StaticDisplayLevels="2">