我正在开发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)
到而不是获取子节点,除了祖先当前网站。
答案 0 :(得分: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;
}
}
}
可能不是最佳解决方案......但 解决方案。
答案 1 :(得分:0)
如果要进行自定义编码解决方案,可以创建一个继承自HierarchicalDataBoundControl的类。使用您的masterpage / pagelayout中的PortalSiteMapDataSource将其连接起来。这将使您可以完全控制输出,并且可以进行优化。
答案 2 :(得分:0)
您的代码是什么样的......使用标准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);
}
}
}
}
}
答案 3 :(得分:0)
这是另一个更优雅的选择。 http://sharepoint2010customnavigation.blogspot.com/