Unless you want to hard code the links or use some custom data source
I only know two different ways to do this, the bad and the horrible way.
The horrible way
Set the current SPWeb to the desired SPWeb and then initialize the menu, for example in a UserControl:
using (var site = new SPSite("http://localhost"))
{
using (var web = site.OpenWeb())
{
var request = new HttpRequest("", web.Url, "");
var sw = new StringWriter();
var response = new HttpResponse(sw);
var originalRequest = HttpContext.Current;
HttpContext.Current = new HttpContext(request, response);
SPControl.SetContextWeb(HttpContext.Current, web);
var siteMapDataSource = new PortalSiteMapDataSource
{
SiteMapProvider = "GlobalNavSiteMapProvider"
};
var menu = new AspMenu {DataSource = siteMapDataSource};
menu.DataBind();
Controls.Add(menu);
HttpContext.Current = originalRequest;
SPControl.SetContextWeb(HttpContext.Current, SPContext.Current.Web);
}
}
The bad way
(and probably not working properly)
Create your own provider which fetches the navigation directly from the SPWeb:
public class CustomSiteMapProvider : PortalSiteMapProvider
{
private const string SiteUrl = "http://localhost";
private static IEnumerable<SPNavigationNode> GetNavigationNodes(string url)
{
using (var site = new SPSite(SiteUrl))
{
using (var web = site.OpenWeb(url))
{
return PublishingWeb.GetPublishingWeb(web).Navigation.GlobalNavigationNodes.
Cast<SPNavigationNode>().ToList();
}
}
}
public override SiteMapNodeCollection GetChildNodes(SiteMapNode node)
{
var navNodes = GetNavigationNodes(node.Url).ToList();
var navNode = navNodes.FirstOrDefault(n => n.Url == node.Url);
if (navNode != null) navNodes= navNode.Children.Cast<SPNavigationNode>().ToList();
var nodes = navNodes.Select(n =>
new SiteMapNode(this, n.Url, n.Url, n.Title)).ToArray();
return new SiteMapNodeCollection(nodes);
}
protected override SiteMapNode GetRootNodeCore()
{
var publishingNodes = GetNavigationNodes("/");
var node = publishingNodes.FirstOrDefault();
if (node == null) return null;
node = node.Parent;
return new SiteMapNode(this, node.Url, node.Url, node.Title);
}
}
Use it like this:
var menu = new AspMenu
{
DataSource = new SiteMapDataSource
{
Provider = new CustomSiteMapProvider()
}
};
menu.DataBind();
Controls.Add(menu);
Note that you must call site.OpenWeb for every child SPWeb as SPNavigationNode might have 0 .Children.
Also note that it is using Publishing and Portal, but you can also extend from for example SiteMapProvider for provider (must include more methods)
and for nodes you can use web.Navigation.GlobalNodes.