Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 58677
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 10, 20262026-05-10T17:53:07+00:00 2026-05-10T17:53:07+00:00

I’m trying to configure the Quick Launch menu to only display the ancestors and

  • 0

I’m trying to configure the Quick Launch menu to only display the ancestors and descendant nodes of the currently select node. The menu also needs to display all the childern of the root node. More simply:

Given a site map of:

RootSite

—SubSite1 = navigation set at ‘Display the current site, the navigation items below the current site, and the current site’s siblings’

—–Heading1 = navigation set at ‘Display the same navigation items as the parent site’

——-Page1 = navigation set at ‘Display the same navigation items as the parent site’

——-Page2 = navigation set at ‘Display the same navigation items as the parent site’

—–Heading2 = navigation set at ‘Display the same navigation items as the parent site’

—SubSite2 = navigation set at ‘Display the current site, the navigation items below the current site, and the current site’s siblings’

—–Heading1 = navigation set at ‘Display the same navigation items as the parent site’

SiteMapProvider configuration:

<PublishingNavigation:PortalSiteMapDataSource ID='SiteMapDS' Runat='server' SiteMapProvider='CurrentNavSiteMapProvider' EnableViewState='true' StartFromCurrentNode='true' ShowStartingNode='false'/> 

The expected and actual behavior of the Quick Launch menu displayed at SubSite1 is:

—SubSite1

—–Heading1

——-Page1

——-Page2

—–Heading2

—SubSite2

The expected behavior of the menu after navigating to Heading1 of SubSite2:

—SubSite1

—SubSite2

—–Heading1

What I actually see after navigating to Heading1 of SubSite2:

—SubSite1

—–Heading1

——-Page1

——-Page2

—–Heading2

—SubSite2

—–Heading1

This does not match what I expect to see if I set the Heading1 navigation to ‘Display the same navigation items as the parent site’ and SubSite2 is set to ‘Display the current site, the navigation items below the current site, and the current site’s siblings’. I expect Heading1 to inherit the navigation item of SubSite2 with the SubSite1 items collapsed from view. I’ve also played with the various Trim… attributes without success. Any help will be greatly appreciated!

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. 2026-05-10T17:53:08+00:00Added an answer on May 10, 2026 at 5:53 pm

    I followed @Nat’s guidance into the murky world Sharepoint webparts to achieve the behavior I described above. My approach was to roll my own version of the MossMenu webpart that Microsoft has released through the ECM Team Blog. This code is based on the native AspMenu control. I used this control to ‘intercept’ the native SiteMapDataSource injected into through DataSourceId attribute in the markup and create a new XML data source to exhibit the desired behavior. I’ve included the final source code at the end of this wordy answer. Here are the bits from the master page markup:

    <%@ Register TagPrefix='myCustom' Namespace='YourCompany.CustomWebParts'    Assembly='YourCompany.CustomWebParts, Version=1.0.0.0, Culture=neutral,    PublicKeyToken=9f4da00116c38ec5' %>  ...  <myCustom:MossMenu ID='CurrentNav' runat='server' datasourceID='SiteMapDS'     orientation='Vertical' UseCompactMenus='true' StaticDisplayLevels='6'     MaximumDynamicDisplayLevels='0' StaticSubMenuIndent='5' ItemWrap='false'     AccessKey='3' CssClass='leftNav'     SkipLinkText='<%$Resources:cms,masterpages_skiplinktext%>'>     <LevelMenuItemStyles>         <asp:MenuItemStyle CssClass='Nav' />         <asp:MenuItemStyle CssClass='SecNav' />     </LevelMenuItemStyles>     <StaticHoverStyle CssClass='leftNavHover'/>     <StaticSelectedStyle CssClass='leftNavSelected'/>     <DynamicMenuStyle CssClass='leftNavFlyOuts' />     <DynamicMenuItemStyle CssClass='leftNavFlyOutsItem'/>     <DynamicHoverStyle CssClass='leftNavFlyOutsHover'/> </myCustom:MossMenu>  <PublishingNavigation:PortalSiteMapDataSource ID='SiteMapDS' Runat='server'      SiteMapProvider='CurrentNavSiteMapProvider' EnableViewState='true'      StartFromCurrentNode='true' ShowStartingNode='false'/>  ... 

    I followed the excellent step-by-step instructions to create my custom web part in the comments section of the MossMenu webpart at ‘Wednesday, September 19, 2007 7:20 AM by Roel’. In my googling, I also found something to configure a Sharepoint site to display exceptions in the same lovely way that ASP.NET does by making the web.config changes here.

    I decided to call my custom behavior a ‘compact menu’ so I created a UseCompactMenus property on the control. If you don’t set this attribute in the markup to true, the control will behave identically to an AspMenu control.

    My application has the user always starting from the home page at the site map root. I can have the custom control store the initial (complete) site map when the root page is displayed. This is stored in a static string for use in the customizing behavior. If you application doesn’t follow this assumption, the control will not work as expected.

    On the initial application page, only the direct child pages to the root page are displayed in the menu. Clicking on these menu nodes will open all the child nodes under it but keeps the sibling nodes ‘closed’. If you click on one of the other sibling nodes, it collapses the current node and it opens the newly selected node. That’s it, enjoy!!

    using System; using System.Text; using System.ComponentModel; using System.Collections.Generic; using System.Security.Permissions; using System.Xml; using System.Xml.Serialization;  using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.Design.WebControls;  using Microsoft.SharePoint; using Microsoft.SharePoint.Utilities; using Microsoft.SharePoint.Security;  namespace YourCompany.CustomWebParts {     [AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]     [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]     [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]     [SharePointPermission(SecurityAction.InheritanceDemand, ObjectModel = true)]     [Designer(typeof(MossMenuDesigner))]     [ToolboxData('<{0}:MossMenu runat=\'server\' />')]     public class MossMenu : System.Web.UI.WebControls.Menu     {         private string idPrefix;          // a url->menuItem dictionary         private Dictionary<string, System.Web.UI.WebControls.MenuItem> menuItemDictionary =             new Dictionary<string, System.Web.UI.WebControls.MenuItem>(StringComparer.OrdinalIgnoreCase);          private bool customSelectionEnabled = true;         private bool selectStaticItemsOnly = true;          private bool performTargetBinding = true;          //** Variables used for compact menu behavior **//         private bool useCompactMenus = false;         private static bool showStartingNode;         private static string originalSiteMap;          /// <summary>         /// Controls whether or not the control performs compacting of the site map to display only ancestor and child nodes of the selected and first level root childern.         /// </summary>         [Category('Behavior')]         public bool UseCompactMenus         {             get             {                 return this.useCompactMenus;             }             set             {                 this.useCompactMenus = value;             }         }          /// <summary>         /// Controls whether or not the control performs custom selection/highlighting.         /// </summary>         [Category('Behavior')]         public bool CustomSelectionEnabled         {             get             {                 return this.customSelectionEnabled;             }             set             {                 this.customSelectionEnabled = value;             }         }          /// <summary>         /// Controls whether only static items may be selected or if         /// dynamic (fly-out) items may be selected too.         /// </summary>         [Category('Behavior')]         public bool SelectStaticItemsOnly         {             get             {                 return this.selectStaticItemsOnly;             }             set             {                 this.selectStaticItemsOnly = value;             }         }          /// <summary>         /// Controls whether or not to bind the Target property of any menu         /// items to the Target property in the SiteMapNode's Attributes         /// collection.         /// </summary>         [Category('Behavior')]         public bool PerformTargetBinding         {             get             {                 return this.performTargetBinding;             }             set             {                 this.performTargetBinding = value;             }         }          /// <summary>         /// Gets the ClientID of this control.          /// </summary>         public override string ClientID         {             [SharePointPermission(SecurityAction.Demand, ObjectModel = true)]             get             {                 if (this.idPrefix == null)                 {                     this.idPrefix = SPUtility.GetNewIdPrefix(this.Context);                 }                  return SPUtility.GetShortId(this.idPrefix, this);             }         }          [SharePointPermission(SecurityAction.Demand, ObjectModel = true)]         protected override void OnMenuItemDataBound(MenuEventArgs e)         {             base.OnMenuItemDataBound(e);              if (this.customSelectionEnabled)             {                 // store in the url->item dictionary                 this.menuItemDictionary[e.Item.NavigateUrl] = e.Item;             }              if (this.performTargetBinding)             {                 // try to bind to the Target property if the data item is a SiteMapNode                 SiteMapNode smn = e.Item.DataItem as SiteMapNode;                 if (smn != null)                 {                     string target = smn['Target'];                     if (!string.IsNullOrEmpty(target))                     {                         e.Item.Target = target;                     }                 }             }         }          /// <id guid='08e034e7-5872-4a31-a771-84cac1dcd53d' />         /// <owner alias='MarkWal'>         /// </owner>         [SharePointPermission(SecurityAction.Demand, ObjectModel = true)]         protected override void OnPreRender(System.EventArgs e)         {              SiteMapDataSource dataSource = this.GetDataSource() as SiteMapDataSource;             SiteMapProvider provider = (dataSource != null) ? dataSource.Provider : null;              if (useCompactMenus && dataSource != null && provider != null)             {                 showStartingNode = dataSource.ShowStartingNode;                  SiteMapNodeCollection rootChildNodes = provider.RootNode.ChildNodes;                  if (provider.CurrentNode.Equals(provider.RootNode))                 {                     //** Store original site map for future use in compacting menus **//                     if (originalSiteMap == null)                     {                         //Store original SiteMapXML for future adjustments:                         XmlDocument newSiteMapDoc = new XmlDocument();                         newSiteMapDoc.LoadXml('<?xml version='1.0' ?>'                             + '<siteMapNode title='' + provider.RootNode.Title                             + '' url='' + provider.RootNode.Url                             + '' />');                          foreach (SiteMapNode node in rootChildNodes)                         {                             XmlNode newNode = GetXmlSiteMapNode(newSiteMapDoc.DocumentElement, node);                              newSiteMapDoc.DocumentElement.AppendChild(newNode);                              //Create XML for all the child nodes for selected menu item:                             NavigateSiteMap(newNode, node);                         }                          originalSiteMap = newSiteMapDoc.OuterXml;                     }                      //This is set to only display the child nodes of the root node on first view:                     this.StaticDisplayLevels = 1;                 }                 else                 {                     //                     //Adjust site map for this page                     //                     XmlDocument newSiteMapDoc = InitializeNewSiteMapXml(provider, rootChildNodes);                      //Clear the current default site map:                     this.DataSourceID = null;                      //Create the new site map data source                     XmlDataSource newSiteMap = new XmlDataSource();                     newSiteMap.ID = 'XmlDataSource1';                     newSiteMap.EnableCaching = false; //Required to prevent redisplay of the previous menu                      //Add bindings for dynamic site map:                     MenuItemBindingCollection bindings = this.DataBindings;                     bindings.Clear();                      MenuItemBinding binding = new MenuItemBinding();                     binding.DataMember = 'siteMapNode';                     binding.TextField = 'title';                     binding.Text = 'title';                     binding.NavigateUrlField = 'url';                     binding.NavigateUrl = 'url';                     binding.ValueField = 'url';                     binding.Value = 'url';                      bindings.Add(binding);                      //Bind menu to new site map:                     this.DataSource = newSiteMap;                      //Assign the newly created dynamic site map:                     ((XmlDataSource)this.DataSource).Data = newSiteMapDoc.OuterXml;                      /** this expression removes the root if initialized: **/                     if (!showStartingNode)                         ((XmlDataSource)this.DataSource).XPath = '/siteMapNode/siteMapNode';                      /** Re-initialize menu data source with new site map: **/                     this.DataBind();                      /** Find depth of current node: **/                     int depth = 0;                     SiteMapNode currNode = provider.CurrentNode;                     do                     {                         depth++;                         currNode = currNode.ParentNode;                     }                     while (currNode != null);                      //Set the StaticDisplayLevels to match the current depth:                     if (depth >= this.StaticDisplayLevels)                         this.StaticDisplayLevels = depth;                 }             }              base.OnPreRender(e);              // output some script to override the default menu flyout behaviour; this helps to avoid             // intermittent 'Operation Aborted' errors             Page.ClientScript.RegisterStartupScript(                 typeof(MossMenu),                 'overrideMenu_HoverStatic',                 'if (typeof(overrideMenu_HoverStatic) == 'function' && typeof(Menu_HoverStatic) == 'function')\n' +                 '{\n' +                     '_spBodyOnLoadFunctionNames.push('enableFlyoutsAfterDelay');\n' +                     'Menu_HoverStatic = overrideMenu_HoverStatic;\n' +                 '}\n',                 true);              // output some script to avoid a known issue with SSL Termination and the ASP.NET             // Menu implementation. http://support.microsoft.com/?id=910444             Page.ClientScript.RegisterStartupScript(                 typeof(MossMenu),                 'MenuHttpsWorkaround_' + this.ClientID,                 this.ClientID + '_Data.iframeUrl='/_layouts/images/blank.gif';',                 true);              // adjust the fly-out indicator arrow direction for locale if not already set             if (this.Orientation == System.Web.UI.WebControls.Orientation.Vertical &&                 ((string.IsNullOrEmpty(this.StaticPopOutImageUrl) && this.StaticEnableDefaultPopOutImage) ||                     (string.IsNullOrEmpty(this.DynamicPopOutImageUrl) && this.DynamicEnableDefaultPopOutImage)))             {                 SPWeb currentWeb = SPContext.Current.Web;                 if (currentWeb != null)                 {                     uint localeId = currentWeb.Language;                      bool isBidiWeb = SPUtility.IsRightToLeft(currentWeb, currentWeb.Language);                      string arrowUrl = '/_layouts/images/' + (isBidiWeb ? 'largearrowleft.gif' : 'largearrowright.gif');                      if (string.IsNullOrEmpty(this.StaticPopOutImageUrl) && this.StaticEnableDefaultPopOutImage)                     {                         this.StaticPopOutImageUrl = arrowUrl;                     }                     if (string.IsNullOrEmpty(this.DynamicPopOutImageUrl) && this.DynamicEnableDefaultPopOutImage)                     {                         this.DynamicPopOutImageUrl = arrowUrl;                     }                 }             }              if (provider == null)             {                 // if we're not attached to a SiteMapDataSource we'll just leave everything alone                 return;             }             else if (this.customSelectionEnabled)             {                 MenuItem selectedMenuItem = this.SelectedItem;                 SiteMapNode currentNode = provider.CurrentNode;                  // if no menu item is presently selected, we need to work our way up from the current                  // node until we can find a node in the menu item dictionary                 while (selectedMenuItem == null && currentNode != null)                 {                     this.menuItemDictionary.TryGetValue(currentNode.Url, out selectedMenuItem);                      currentNode = currentNode.ParentNode;                 }                  if (this.selectStaticItemsOnly)                 {                     // only static items may be selected, keep moving up until we find an item                     // that falls within the static range                     while (selectedMenuItem != null && selectedMenuItem.Depth >= this.StaticDisplayLevels)                     {                         selectedMenuItem = selectedMenuItem.Parent;                     }                      // if we found an item to select, go ahead and select (highlight) it                     if (selectedMenuItem != null && selectedMenuItem.Selectable)                     {                         selectedMenuItem.Selected = true;                     }                 }             }         }          private XmlDocument InitializeNewSiteMapXml(SiteMapProvider provider, SiteMapNodeCollection rootChildNodes)         {             /** Find the level 1 ancestor node of the current node: **/             SiteMapNode levelOneAncestorOfSelectedNode = null;             SiteMapNode currNode = provider.CurrentNode;             do             {                 levelOneAncestorOfSelectedNode = (currNode.ParentNode == null ? levelOneAncestorOfSelectedNode : currNode);                 currNode = currNode.ParentNode;             }             while (currNode != null);              /** Initialize base SiteMapXML **/             XmlDocument newSiteMapDoc = new XmlDocument();             newSiteMapDoc.LoadXml(originalSiteMap);              /** Prune out the childern nodes that shouldn't display: **/             currNode = provider.CurrentNode;             do             {                 if (currNode.ParentNode != null)                 {                     SiteMapNodeCollection currNodeSiblings = currNode.ParentNode.ChildNodes;                     foreach (SiteMapNode siblingNode in currNodeSiblings)                     {                         if (siblingNode.HasChildNodes)                         {                             if (provider.CurrentNode.Equals(siblingNode))                             {                                 //Remove all the childerns child nodes from display:                                 SiteMapNodeCollection currNodesChildren = siblingNode.ChildNodes;                                 foreach (SiteMapNode childNode in currNodesChildren)                                 {                                     XmlNode currentXmNode = GetCurrentXmlNode(newSiteMapDoc, childNode);                                      DeleteChildNodes(currentXmNode);                                 }                             }                             else if (!provider.CurrentNode.IsDescendantOf(siblingNode)                                 && !levelOneAncestorOfSelectedNode.Equals(siblingNode))                             {                                 XmlNode currentXmNode = GetCurrentXmlNode(newSiteMapDoc, siblingNode);                                  DeleteChildNodes(currentXmNode);                             }                         }                     }                 }                  currNode = currNode.ParentNode;             }             while (currNode != null);              return newSiteMapDoc;         }          private XmlNode GetCurrentXmlNode(XmlDocument newSiteMapDoc, SiteMapNode node)         {             //Find this node in the original site map:             XmlNode currentXmNode = newSiteMapDoc.DocumentElement.SelectSingleNode(                 '//siteMapNode[@url=''                 + node.Url                 + '']');             return currentXmNode;         }          private void DeleteChildNodes(XmlNode currentXmNode)         {             if (currentXmNode != null && currentXmNode.HasChildNodes)             {                 //Remove child nodes:                 XmlNodeList xmlNodes = currentXmNode.ChildNodes;                 int lastNodeIndex = xmlNodes.Count - 1;                 for (int i = lastNodeIndex; i >= 0; i--)                 {                     currentXmNode.RemoveChild(xmlNodes[i]);                 }             }         }         private XmlNode GetXmlSiteMapNode(XmlNode currentDocumentNode, SiteMapNode currentNode)         {             XmlElement newNode = currentDocumentNode.OwnerDocument.CreateElement('siteMapNode');              XmlAttribute newAttr = currentDocumentNode.OwnerDocument.CreateAttribute('title');             newAttr.InnerText = currentNode.Title;             newNode.Attributes.Append(newAttr);              newAttr = currentDocumentNode.OwnerDocument.CreateAttribute('url');             newAttr.InnerText = currentNode.Url;             newNode.Attributes.Append(newAttr);              return newNode;         }          private void NavigateSiteMap(XmlNode currentDocumentNode, SiteMapNode currentNode)         {             foreach (SiteMapNode node in currentNode.ChildNodes)             {                 //Add this node to structure:                 XmlNode newNode = GetXmlSiteMapNode(currentDocumentNode, node);                 currentDocumentNode.AppendChild(newNode);                  if (node.HasChildNodes)                 {                     //Make a recursive call to add any child nodes:                     NavigateSiteMap(newNode, node);                 }             }         }     }      [PermissionSet(SecurityAction.LinkDemand, Name = 'FullTrust')]     [System.Diagnostics.CodeAnalysis.SuppressMessage('Microsoft.Security', 'CA2117:AptcaTypesShouldOnlyExtendAptcaBaseTypes')]     public sealed class MossMenuDesigner : MenuDesigner     {         [PermissionSet(SecurityAction.Demand, Name = 'FullTrust')]         protected override void DataBind(BaseDataBoundControl dataBoundControl)         {             try             {                 dataBoundControl.DataBind();             }             catch             {                 base.DataBind(dataBoundControl);             }         }          [PermissionSet(SecurityAction.Demand, Name = 'FullTrust')]         public override string GetDesignTimeHtml()         {             System.Web.UI.WebControls.Menu menu = (System.Web.UI.WebControls.Menu)ViewControl;             int oldDisplayLevels = menu.MaximumDynamicDisplayLevels;             string designTimeHtml = string.Empty;              try             {                 menu.MaximumDynamicDisplayLevels = 0;                  // ASP.NET MenuDesigner has some dynamic/static item trick in design time                 // to show dynamic item in design time. We only want to show preview without                 // dynamic menu items.                 designTimeHtml = base.GetDesignTimeHtml();             }             catch (Exception e)             {                 designTimeHtml = GetErrorDesignTimeHtml(e);             }             finally             {                 menu.MaximumDynamicDisplayLevels = oldDisplayLevels;             }              return designTimeHtml;         }     } } 
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am trying to understand how to use SyndicationItem to display feed which is
I want use html5's new tag to play a wav file (currently only supported
I'm trying to select an H1 element which is the second-child in its group
I'm trying to convert HTML to plain text. I get many &\#8217; &\#8220; etc.
Basically, what I'm trying to create is a page of div tags, each has
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
I am trying to render a haml file in a javascript response like so:
In my XML file chapters tag has more chapter tag.i need to display chapters
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.