asp.netmenuparent-childmenuitemaspmenu

Displaying the child items of the current node in a static ASP:Menu


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.


Solution

  • 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">