代码之家  ›  专栏  ›  技术社区  ›  Sixto Saez

Moss 2007中快速启动菜单的显示行为不一致

  •  1
  • Sixto Saez  · 技术社区  · 17 年前

    我正在尝试配置快速启动菜单,以仅显示当前选择节点的祖先和后代节点。菜单还需要显示根节点的所有子节点。更简单地说:

    提供了一张站点地图:

    生根地

    --- 子站点1 =导航设置为“显示当前网站、当前网站下方的导航项以及当前网站的同级网站”

    ----- 标题1 =导航设置为“显示与父站点相同的导航项”

    ----- 第1页 =导航设置为“显示与父站点相同的导航项”

    ----- 第二页 =导航设置为“显示与父站点相同的导航项”

    ----- 标题2 =导航设置为“显示与父站点相同的导航项”

    --- 子站点2 =导航设置为“显示当前网站、当前网站下方的导航项以及当前网站的同级网站”

    ----- 标题1 =导航设置为“显示与父站点相同的导航项”

    SiteMapProvider配置:

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

    子站点1上显示的快速启动菜单的预期和实际行为是:

    --SuffeTe1

    -Healg1

    ---PGE1

    ----PGE 2

    -Healg2

    --Suffiste2

    导航到子网站2的标题1后菜单的预期行为:

    --SuffeTe1

    --Suffiste2

    -Healg1

    导航到子网站2的标题1后,我实际看到的是:

    --SuffeTe1

    -Healg1

    ---PGE1

    ----PGE 2

    -Healg2

    --Suffiste2

    -Healg1

    这与我希望看到的不匹配,如果我将heading1导航设置为“显示 与父网站相同的导航项”和子网站2设置为“显示当前网站、当前网站下方的导航项以及当前网站的同级网站”。我期待 Heading1继承子网站2的导航项,子网站1项从视图中折叠。我也玩过各种各样的 修剪…属性没有成功。任何帮助都将不胜感激!

    3 回复  |  直到 17 年前
        1
  •  2
  •   Sixto Saez    16 年前

    MossMenu webpart

    <%@ 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"/>
    
    ...
    

    here

    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;
            }
        }
    }
    
        2
  •  1
  •   Nat    16 年前
        3
  •  0
  •   Chuck    16 年前
    推荐文章