How to: Add a Subsite to the Top Link Bar or Quick Launch Menu

Applies to: SharePoint Foundation 2010

When you create a subsite through the Microsoft SharePoint Foundation user interface, you can specify whether links to the new site appear in the Quick Launch area and the top link bar of the parent site. You can also add links in both places by writing code that manipulates the parent website's SPWeb.Navigation.TopNavigationBar property and its SPWeb.Navigation.QuickLaunch property.

In the SharePoint Foundation object model, the navigation structure for the top link bar is represented by an instance of the SPNavigationNodeCollection class. To get the collection, first access the website's SPWeb.Navigation property, which returns an SPNavigation object, and then access the TopNavigationBar property of that object.

Warning

If a website is configured to use the top link bar from its parent site, the TopNavigationBar property returns null.

When you have a collection of navigation nodes, construct an SPNavigationNode object to represent the new link, and then call a method of the SPNavigationNodeCollection class to add the node to the top link bar.

  1. Get a reference to the SPWeb object that represents the subsite.

    SPWeb child = site.OpenWeb("parent/child");
    
    Dim child As SPWeb = site.OpenWeb("parent/child")
    
  2. Verify that the subsite is indeed a subsite by testing the value of the IsRootWeb property; also verify that the parent site is not using a shared top link bar by testing the value of its UseShared property.

    if (!child.IsRootWeb && !child.ParentWeb.Navigation.UseShared)
    
    If Not child.IsRootWeb AndAlso Not child.ParentWeb.Navigation.UseShared Then
    
  3. Get the SPNavigationNodeCollection object that represents the parent site's top link bar.

    SPNavigationNodeCollection topnav = child.ParentWeb.Navigation.TopNavigationBar;
    
    Dim topnav As SPNavigationNodeCollection = child.ParentWeb.Navigation.TopNavigationBar
    
  4. Check for an existing link to the subsite by querying the collection for an SPNavigationNode object that has a Url property that has a value equal to the subsite's SPWeb.ServerRelativeUrl property.

    SPNavigationNode node = topnav
        .Cast<SPNavigationNode>()
        .FirstOrDefault(n => n.Url.Equals(child.ServerRelativeUrl));
    
    Dim node As SPNavigationNode = topnav.Cast(Of SPNavigationNode)().FirstOrDefault( _
        Function(n) n.Url.Equals(child.ServerRelativeUrl))
    
  5. If no link exists, construct an SPNavigationNode object to represent a link, and call a method from the SPNavigationNodeCollection class to add it to the parent site's top link bar.

    if (node == null)
    {
        node = new SPNavigationNode(child.Title, child.ServerRelativeUrl);
        node = topnav.AddAsLast(node);
    }
    
    If node Is Nothing Then
    
        node = New SPNavigationNode(child.Title, child.ServerRelativeUrl)
        node = topnav.AddAsLast(node)
    
    End If
    

Example

The following example shows how to add a link to a subsite in the parent site's navigational structure. The example is part of a larger project that uses a web-scoped Feature to add the link. The Feature includes an event handler that implements the SPFeatureReceiver class, and code to create the link and add it to the parent site is in the feature receiver's FeatureActivated method.

If the site where the Feature is activated has subsites, the method looks for a subsite named "ourwiki". If the subsite exists, the method gets a reference to it. If there are no subsites, or there are subsites but none have the name "ourwiki", the method creates one.

Next, the method adds the navigation link to the subsite. If the current site has its own top link bar (that is, it is not using its parent's bar), the link is added to the current site's top link bar. Otherwise, it is added to the current site's Quick Launch menu.

Both Quick Launch and the top link bar are represented by SPNavigationNodeCollection objects. Therefore, at this point the code is the same no matter which collection is the destination for the navigation link. The example first checks whether a link to the subsite is already in the navigation node collection. If it is not, the code creates a link and adds it.

Note

The example code uses several types without qualification. For the code to compile correctly, your feature receiver class must import the following namespaces:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{

    // Get the website where the feature is activated.
    SPWeb parentWeb = properties.Feature.Parent as SPWeb;
    if (parentWeb == null)
        return;

    SPWeb childWeb = null;
    string childName = "ourwiki";

    // If a subsite by that name exists, open it.
    string[] webs = parentWeb.Webs.Names;
    if (webs != null && Array.IndexOf(webs, childName) >= 0)
    {
        childWeb = parentWeb.Webs[childName];
    }

    // Otherwise, create the subsite.
    if (childWeb == null)
    {
        string title = "Wiki";
        string desc = "A place to capture knowledge.";
        uint lcid = parentWeb.Language;

        string templateName = "WIKI#0";

        childWeb = parentWeb.Webs.Add(childName, title, desc, lcid, templateName, false, false);
    }

    // Let the subsite use the parent site's top link bar.
    childWeb.Navigation.UseShared = true;

    // Get a collection of navigation nodes.
    SPNavigationNodeCollection nodes = null;
    if (parentWeb.Navigation.UseShared)
    {

        // Parent site does not have its own top link bar
        // so use the parent's Quick Launch.
        nodes = parentWeb.Navigation.QuickLaunch;
    }
    else
    {

        // Parent site has its own top link bar,
        // so use it.
        nodes = parentWeb.Navigation.TopNavigationBar;
    }

    // Check for an existing link to the subsite.
    SPNavigationNode node = nodes
        .Cast<SPNavigationNode>()
        .FirstOrDefault(n => n.Url.Equals(childWeb.ServerRelativeUrl));

    // No link, so add one.
    if (node == null)
    { 

        // Create the node.
        node = new SPNavigationNode(childWeb.Title, childWeb.ServerRelativeUrl);

        // Add it to the collection.
        node = nodes.AddAsLast(node);
    }

    childWeb.Dispose();
    parentWeb.Dispose();
}
Public Overrides Sub FeatureActivated(ByVal properties As SPFeatureReceiverProperties)

    'Get the website where the feature is activated.
    Dim parentWeb As SPWeb = TryCast(properties.Feature.Parent, SPWeb)
    If parentWeb Is Nothing Then
        Return
    End If

    Dim childWeb As SPWeb = Nothing
    Dim childName As String = "ourwiki"

    ' If a subsite by that name exists, open it.
    Dim webs As String() = parentWeb.Webs.Names
    If webs IsNot Nothing AndAlso Array.IndexOf(webs, childName) >= 0 Then
        childWeb = parentWeb.Webs(childName)
    End If

    ' Otherwise, create the subsite.
    If childWeb Is Nothing Then
        Dim title As String = "Wiki"
        Dim desc As String = "A place to capture knowledge."
        Dim lcid As UInteger = parentWeb.Language

        Dim templateName As String = "WIKI#0"

        childWeb = parentWeb.Webs.Add(childName, title, desc, lcid, _
                                        templateName, False, False)
    End If

    ' Let the subsite use the parent site's top link bar.
    childWeb.Navigation.UseShared = True

    ' Get a collection of navigation nodes.
    Dim nodes As SPNavigationNodeCollection = Nothing

    If parentWeb.Navigation.UseShared Then

        ' Parent site does not have its own top link bar
        ' so use the parent's Quick Launch.
        nodes = parentWeb.Navigation.QuickLaunch
    Else

        ' Parent site has its own top link bar,
        ' so use it.
        nodes = parentWeb.Navigation.TopNavigationBar
    End If

    ' Check for an existing link to the subsite.
    Dim node As SPNavigationNode = nodes.Cast(Of SPNavigationNode)().FirstOrDefault( _
        Function(n) n.Url.Equals(childWeb.ServerRelativeUrl))

    ' No link, so add one.
    If node Is Nothing Then

        ' Create the node.
        node = New SPNavigationNode(childWeb.Title, childWeb.ServerRelativeUrl)

        ' Add it to the collection.
        node = nodes.AddAsLast(node)
    End If

    childWeb.Dispose()
    parentWeb.Dispose()
End Sub

In the SharePoint Foundation object model, each navigation link on the Quick Launch menu is represented by an instance of the SPNavigationNode class. The top level of the Quick Launch menu structure is a collection of SPNavigationNode objects represented by an instance of the SPNavigationNodeCollection class. The nodes on this first level of the menu are the headings—List, Libraries, Sites, and so on. Each heading has a SPNavigationNode.Children property that returns a collection of nodes that represent the links below the heading.

To insert a link below the Sites heading, you can call the AddToQuickLaunch method and specify the Sites heading. The method accepts two arguments: an SPNavigationNode object that represents the new link, and an SPQuickLaunchHeading enumeration value that specifies the heading that should receive the link.

SPNavigation nav = web.ParentWeb.Navigation;
SPNavigationNode node = new SPNavigationNode(web.Title, web.ServerRelativeUrl);
node = nav.AddToQuickLaunch(node, SPQuickLaunchHeading.Sites);
Dim nav As SPNavigation = web.ParentWeb.Navigation
Dim node As SPNavigationNode = New SPNavigationNode(web.Title, web.ServerRelativeUrl)
node = nav.AddToQuickLaunch(node, SPQuickLaunchHeading.Sites)

You will of course want to check to make sure that a link to the subsite does not already exist below the Sites heading. One way to check is explained in the following procedure.

  1. Get a reference to the SPWeb object that represents the subsite.

    SPWeb child = site.OpenWeb("parent/child");
    
    Dim child As SPWeb = site.OpenWeb("parent/child")
    
  2. Verify that the subsite is in fact a subsite and not the root website of the collection.

    if (!child.IsRootWeb)
    
    If Not child.IsRootWeb Then
    
  3. Get the SPNavigation object for the parent website.

    SPNavigation nav = web.ParentWeb.Navigation;
    
    Dim nav As SPNavigation = web.ParentWeb.Navigation
    
  4. Get the Sites heading on the Quick Launch menu by calling the GetNodeById method, passing the integer equivalent of SPQuickLaunchHeading.Sites.

    SPNavigationNode sitesHeading = nav.GetNodeById((int)SPQuickLaunchHeading.Sites);
    
    Dim sitesHeading As SPNavigationNode = nav.GetNodeById(CInt(SPQuickLaunchHeading.Sites))
    

    Note

    If the Quick Launch menu does not yet have a Sites heading, the call to GetNodeById returns null.

  5. Check for an existing link to the subsite by querying the children of the Sites heading for an SPNavigationNode object that has a Url property with a value equal to the subsite's SPWeb.ServerRelativeUrl property.

    SPNavigationNode newNode = null;
    if (sitesHeading != null)
    {
        newNode = sitesHeading
            .Children
            .Cast<SPNavigationNode>()
            .FirstOrDefault(n => n.Url == web.ServerRelativeUrl);
    }
    
    Dim newNode As SPNavigationNode = Nothing
    If sitesHeading IsNot Nothing Then
        newNode = sitesHeading.Children.Cast(Of SPNavigationNode)().FirstOrDefault( _
            Function(n) n.Url = web.ServerRelativeUrl)
    End If
    
  6. If no link exists, construct an SPNavigationNode object to represent the link, and call the AddToQuickLaunch method to add it to the parent site's Quick Launch menu below the Sites heading.

    if (newNode == null)
    {
    
        // Create the link.
        newNode = new SPNavigationNode(web.Title, web.ServerRelativeUrl);
    
        // Add it to the parent site's Quick Launch.
        newNode = nav.AddToQuickLaunch(newNode, SPQuickLaunchHeading.Sites);
    }
    
    If newNode Is Nothing Then
    
        ' Create the link.
        newNode = New SPNavigationNode(web.Title, web.ServerRelativeUrl)
    
        ' Add it to the parent site's Quick Launch.
        newNode = nav.AddToQuickLaunch(newNode, SPQuickLaunchHeading.Sites)
    End If
    

Example

The following example is a console application that illustrates the procedure for inserting a link to a subsite on the parent site's Quick Launch menu. You could add similar code (suitably modified) in the FeatureActivated method of a Feature receiver that creates a subsite.

using System;
using System.Linq;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Navigation;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            using (SPSite site = new SPSite("https://localhost"))
            {

                // Get the subsite.
                using (SPWeb web = site.OpenWeb("parent/child"))
                {
                    if (!web.IsRootWeb)
                    { 

                        // Get the parent site's navigator.
                        SPNavigation nav = web.ParentWeb.Navigation;

                        // Get the Sites heading.
                        SPNavigationNode sitesHeading = nav.GetNodeById((int)SPQuickLaunchHeading.Sites);

                        // Check if a link to the child already exists.
                        SPNavigationNode newNode = null;
                        if (sitesHeading != null)
                        {
                            newNode = sitesHeading
                                .Children
                                .Cast<SPNavigationNode>()
                                .FirstOrDefault(n => n.Url == web.ServerRelativeUrl);
                        }

                        // No link, so create one.
                        if (newNode == null)
                        {

                            // Create the link.
                            newNode = new SPNavigationNode(web.Title, web.ServerRelativeUrl);

                            // Add it to the parent site's Quick Launch.
                            newNode = nav.AddToQuickLaunch(newNode, SPQuickLaunchHeading.Sites);
                        }

                        Console.WriteLine("A link to {0} is on the Quick Launch for {1}", newNode.Title, nav.Web.Title);
                    }
                }
            }
            Console.Write("\nPress ENTER to continue....");
            Console.ReadLine();
        }
    }
}
Imports System
Imports Microsoft.SharePoint
Imports Microsoft.SharePoint.Navigation

Module ConsoleApp

    Sub Main()

        Using site As New SPSite("https://localhost")

            Using web As SPWeb = site.OpenWeb("parent/child")

                If Not web.IsRootWeb Then

                    ' Get the parent site's navigator.
                    Dim nav As SPNavigation = web.ParentWeb.Navigation

                    ' Get the Sites heading.
                    Dim sitesHeading As SPNavigationNode = nav.GetNodeById(CInt(SPQuickLaunchHeading.Sites))

                    ' Check if a link to the child already exists.
                    Dim newNode As SPNavigationNode = Nothing
                    If sitesHeading IsNot Nothing Then

                        newNode = sitesHeading.Children.Cast(Of SPNavigationNode)().FirstOrDefault( _
                            Function(n) n.Url = web.ServerRelativeUrl)
                    End If

                    ' No link, so create one.
                    If newNode Is Nothing Then

                        ' Create the link.
                        newNode = New SPNavigationNode(web.Title, web.ServerRelativeUrl)

                        ' Add it to the parent site's Quick Launch.
                        newNode = nav.AddToQuickLaunch(newNode, SPQuickLaunchHeading.Sites)
                    End If

                    Console.WriteLine("A link to {0} is on the Quick Launch for {1}", newNode.Title, nav.Web.Title)
                End If

            End Using

        End Using

        Console.Write(vbCrLf & "Press ENTER to continue....")
        Console.Read()
    End Sub

End Module

See Also

Tasks

How to: Customize the Display of Quick Launch

How to: Display or Hide Quick Launch

Concepts

Adding Links to the Top Link Bar

How to: Share the Top Link Bar Between Sites