【问题标题】:SharePoint Custom Current Navigation / PortalSiteMapProviderSharePoint 自定义当前导航/PortalSiteMapProvider
【发布时间】:2011-02-05 20:22:27
【问题描述】:

我正在处理 SharePoint 解决方案上的自定义当前(左)导航。

我需要的是导航的根是一个变体网络,即根网络的直接子级。作为此变体的直接子级的所有站点和页面都应该可见,但不会展开。只有作为当前站点的祖先的站点才应该扩展...一直到当前站点/页面。

一个例子...如果我从页面http://spsite.ex/variation/site2/subsite2.1/subsite2.1.1/subsite2.1.1.3/page.aspx开始,我应该看到...

Site1
Site2
    SubSite2.1
        SubSite2.1.1
            SubSite2.1.1.1
            SubSite2.1.1.2
            SubSite2.1.1.3
                page.aspx (YOU ARE HERE)
    SubSite2.2
    Site2Page1
    Site2Page2
Site3
Site4
Site5

如果我随后点击SubSite2.1 的链接,我应该会看到类似...

Site1
Site2
    SubSite2.1 (YOU ARE HERE)
        SubSite2.1.1
    SubSite2.2
    Site2Page1
    Site2Page2
Site3
Site4
Site5

如果我随后导航到 http://spsite.ex/variation/site5/subsite5.1/page.aspx,我应该会看到类似...

Site1
Site2
Site3
Site4
Site5
    SubSite5.1
        SubSite5.1.1
        page.aspx (YOU ARE HERE)

我已经编写了一个解决方案,但我觉得它不应该让我感到自豪;我给了AspMenu 一个近乎无限的StaticDisplayLevels,然后扩展PortalSiteMapProvider,覆盖GetChildNode(node)获取子节点,当前网络的祖先除外。

【问题讨论】:

  • 你的解决方案有效吗?
  • 是的!我想我正在寻找一种验证,证明我已经了解我在做什么以及我应该如何去做,或者我是否需要购买一些错误的代码偏移量:PI 的意思是,接近无穷大StaticDisplayLevels。 ..如果PortalSiteMapDataSourceStartingNodeOffset 为0(从根)我得到例外......所以它闻起来有点味道。
  • 这是 Sharepoint 真正应该允许您使用开箱即用的导航控件做的事情,看看它在互联网上的使用情况 - 可能在之后的下一个版本中2010...
  • 我正在寻找类似的东西。您的解决方案是否有效,如果有效,您能否分享一下您的代码?
  • @ScottE - 我希望可以,但我不再在那家公司工作,而且我没有保留副本,因为我对解决方案并不感到自豪......我会看看一些 msdn 阅读会刷新我的记忆。

标签: asp.net sharepoint sharepoint-2007 navigation portalsitemapprovider


【解决方案1】:

@ScottE,我想我已经设法重现了我用来解决这个问题的代码:

using System;
using System.Web;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.Publishing.Navigation;

namespace StackOverflow.SharePoint
{
    public class Question2602537PortalSiteMapProvider : PortalSiteMapProvider
    {

        public override SiteMapNodeCollection GetChildNodes(System.Web.SiteMapNode node)
        {
            bool expandChildNodes = false;
            if (SPContext.Current != null)
            {
                expandChildNodes = NodeIsAncestorOfCurrentNode(node);
            }

            if (expandChildNodes)
            {
                return base.GetChildNodes(node);
            }
            else
            {
                return new SiteMapNodeCollection();
            }
        }

        private bool NodeIsAncestorOfCurrentNode(System.Web.SiteMapNode node)
        {
            bool returnvalue = false;
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite thisSite = new SPSite(SPContext.Current.Site.ID))
                {
                    using (SPWeb nodeWeb = this.OpenWeb(thisSite, node))
                    {
                        using (SPWeb currentWeb = this.OpenNavWeb(thisSite))
                        {
                            returnvalue = this.AncestorDescendantWebs(nodeWeb, currentWeb);
                        }
                    }
                }
            });
            return returnvalue;
        }

        private SPWeb OpenWeb(SPSite thisSite, System.Web.SiteMapNode node)
        {
            // need to use Uri objects, as sometimes the node URL contains a query string
            // but calling OpenWeb(...) with a ? in your URL throws an exception
            // using Uri.LocalPath removes the Query String
            Uri siteUri = new Uri(thisSite.Url);
            Uri nodeUri = new Uri(siteUri, node.Url);
            return thisSite.OpenWeb(nodeUri.LocalPath.Split(new string[] { "/_" }, StringSplitOptions.RemoveEmptyEntries)[0], false);
        }

        private SPWeb OpenNavWeb(SPSite thisSite)
        {
            using (SPWeb currentWeb = thisSite.OpenWeb(this.CurrentWeb.ID))
            {
                SPWeb web = currentWeb;
                PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);

                // Loop all the way up the webs until we find the one which doesn't inherit
                // (there's gotta be a better way of doing this)
                while (publishingWeb.InheritCurrentNavigation &&
                    !web.ID.Equals(thisSite.RootWeb.ID))
                {
                    web = web.ParentWeb;
                    publishingWeb = PublishingWeb.GetPublishingWeb(web);
                }

                return web;
            }
        }

        private bool AncestorDescendantWebs(SPWeb ancestor, SPWeb descendant)
        {
            // check the URLs to determine if descendant is a subweb or ancestor
            // (there's gotta be a better way...)
            if ((descendant.ServerRelativeUrl + "/").ToUpper().StartsWith(ancestor.ServerRelativeUrl.ToUpper() + "/"))
            {
                return true;
            }
            return false;
        }

    }
}

也许不是最佳解决方案...而是一个解决方案。

【讨论】:

  • @Pauli Østerø's answer我想知道是否可以使用SiteMap.CurrentNode.IsEqualToOrDescendantOf(SiteMapNode)方法来避免创建这么多SPWeb对象。
【解决方案2】:

如果您想做一个自定义编码的解决方案,您可以创建一个继承自 HierarchicalDataBoundControl 的类。将它与您的 masterpage/pagelayout 中的 PortalSiteMapDataSource 连接起来。这将使您可以完全控制输出并尽可能优化。

【讨论】:

    【解决方案3】:

    你的代码是什么样子的......像这样使用标准 SiteMapProvider 的典型菜单不能比这简单得多

    public class SideMenu : Control
    {
        private SiteMapNode _rootNode = SiteMap.RootNode;
        public SiteMapNode RootNode
        {
            get { return this._rootNode; }
            set { this._rootNode = value; }
        }
    
        public SideMenu()
        {
            ID = "SideMenu";
        }
    
        protected override void CreateChildControls()
        {
            var div = new HtmlGenericControl("div");
            div.Attributes.Add("id", ID);
            Controls.Add(div);
    
            CreateMenuNodes(RootNode, div);
    
            base.CreateChildControls();
        }
    
        protected override void Render(HtmlTextWriter writer)
        {
            if (!ChildControlsCreated)
            {
                CreateChildControls();
            }
    
            base.Render(writer);
        }
    
        private void CreateMenuNodes(SiteMapNode node, HtmlGenericControl container)
        {
            if (node.HasChildNodes)
            {
                var ul = new HtmlGenericControl("ul");
                container.Controls.Add(ul);
    
                foreach (SiteMapNode child in node.ChildNodes)
                {
                    var li = new HtmlGenericControl("li");
                    ul.Controls.Add(li);
    
                    var a = new HtmlAnchor()
                    {
                        InnerHtml = HttpUtility.HtmlEncode(child.Title),
                        Title = child.Title,
                        HRef = child.Url
                    };
    
                    li.Controls.Add(a);
    
                    if (SiteMap.CurrentNode.IsEqualToOrDescendantOf(child))
                    {
                        li.Attributes["class"] = "selected";
    
                        CreateMenuNodes(child, li);
                    }
                }
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      这是另一个更优雅的选项。 http://sharepoint2010customnavigation.blogspot.com/

      【讨论】:

      • 那篇文章是关于 SharePoint 2010 的;我没有在我的问题中具体说明,但它是关于 MOSS2007
      猜你喜欢
      • 1970-01-01
      • 2011-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-18
      • 1970-01-01
      相关资源
      最近更新 更多