A custom top navigation manager for SharePoint Site

SharePoint Navigation and specifically the possible ways of updating top navigation and how to implement a custom top navigation manager. The reader can get clear idea about how to manage the navigation using Object Model.

Assumptions

We assume that the reader is familiar with Visual Studio 2008 and WSPBuilder projects template.

Introduction

Web site navigation is the primary interface provider for site users to navigate the site and pages. In WSS/MOSS there are couple of navigation providers provided by Microsoft. Those out-of-the-box navigation providers are featured enough that any user can easily navigation to the site. Also Microsoft provided them as customizable so the developer / designer can change the navigation in their way to provide better user experience. This includes the custom styling, adding more or relavant nodes to the navigation.

A typical SharePoint site has mainly three navigations or navigation nodes are there.

  1. Global Navigation Nodes

  2. Quick Launch Nodes

  3. Top Navigation Nodes

In this article we will look around the Top Navigation Node and discuss how to manage that nodes from SharePoint site also discuss how we can add/remove the nodes in/from the Top Navigation Nodes.

Top Navigation of SharePoint site

The top navigation is the main navigation of any SharePoint site and it is display at the top of the site below the title and site image as shown in the below image.

This Top Navigation basically contains the node of the main site and its sub sites. We can add some more nodes to this top navigation by going to Site Settings.

On Site Settings page under the Look and Feel group there is a link for Top link bar. Using this we can get the page from where we can manage the top link bar nodes also can change the orders of the nodes.

On this page we can add the new nodes which reside on the top level. We can't add any child node to those nodes. To add any child node to any existing node we have to modify that using code. Microsoft SharePoint Object Model provides this customization by the SPNavigationNode, SPNavigationNodeCollection object in the Microsoft.SharePoint.Navigation namespace. The SPWeb object has the Navigation Property which has sub properties named GlobalNodes, QuickLaunch and TopNavigationBar. These three properties provide the SPNavigationNodeCollection which are displayed on the rendered page. As for our example, we can add the new node using code to the TopNavigationBar node collection like the following way.

   private void AddNode(string title, string url, int parentNodeIndex)
        {
            SPNavigationNode newNode = new SPNavigationNode(title, url);
            SPNavigationNodeCollection topNavigationBar = m_theWeb.Navigation.TopNavigationBar;
             if (parentNodeIndex > -1)
            {
                SPNavigationNode parentNode = topNavigationBar[parentNodeIndex];
                 parentNode.Children.AddAsLast(newNode);
            }
            else
                 topNavigationBar.AddAsLast(newNode);
             m_theWeb.Update();
        }

The SPNavigationNodeCollection has 3 different methods to add new nodes in the collection.

  1. Add(SPNavigationNode node, SPNavigationNode previousNode) - This method add a new node after the provided previous node in the collection. This method is used when you want to add any new node in middle of the collection.

  2. AddAsFirst(SPNavigationNode node) - As the method name shows, the new node is added at the first position in the collection.

  3. AddAsLast(SPNavigationNode node) - As the method name shows, the new node is added at the last position in the collection.

Also each SPNavigationNode has a property called Children, which serves as the collection of child nodes. By this way we can add new child nodes to the top level nodes in Top Navigation Bar. This is achieved using any console application or windows or ASP.NET application. But this is not a proper solution for managing the Top Navigation, as this requires providing some extra application to manage also, the end use has difficulties for handling this. So, why not to provide a page which is used same like the Top Link Bar page and its url is added in the Look and Feel group????

To provide this facility I've developed a feature and write custome code to manage the Top Navigation for any particular site or sub site. This feature is activated on a web level, so any one can use it for a particular web site or sub site only also.

Following is the screen image of my developed Top Navigation Manager.

Let me explain the functionality

First of all about the feature - I've created a feature that will be activated on the web site. When this feature is activated a new link name "Manage Top Navigation" is added in the "Look and Feel" group in on Site Settings page. We can achieve this by adding a custom action element node  in the feature's element.xml file like as below

<CustomAction Id="TopNavigationManagerSettingsID" Title="Manage Top Navigation"
                
Location="Microsoft.SharePoint.SiteSettings" GroupId="Customization"
                
Sequence="106" RequireSiteAdministrator="TRUE">
    <UrlAction Url="_layouts/CustomTopNavigationManager.aspx"/>    
  </CustomAction>

The Url value of the UrlAction node in CustomAction element provides the link to our manager page (discussed below).

I've developed a new page with provide the functionality to manage the top navigation. The main functionality implementation resides in a web part and that web part is added on the page. The page is also deployed with this feature and you can find that page in the layouts directory at C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS of the server. To deploy the page you have to add the following tag in the elements.xml file before the closing of the Elements tag.

<Module Path="PageTemplates" Url="ApplicationPages">
    
<File Url="CustomTopNavigationManager.aspx" Type="Ghostable" />
  
</Module>

The Type="Ghostable" indicates that the page is served from the file system for all the sites.

Now, the development of web part is quite same as others...

I've used a treeview to display the existing top navigation node on the page. The treeview is displayed on the left side of the page. In the right side the couple of text boxes and buttons are there to manage and add new nodes in the navigation collection.

The title and url values displays the current selected node in the left tree view. At the page load, I've selected the first node so the title and url contains the title and url for that node.

The Add node button provides the facility to add new top level node or child node. To add a new node as the child of the current selected node you need to  check the check box. By default the check box is checked.

The Update button provides the facility to update the title and url of the current selected node.

The Delete button deletes the current selected node.

Following is the code snippet for adding a new child to the existing node

private void m_btnSaveChild_Click(object sender, EventArgs e)
         {
             
if (!ValidChildInputs())
                 
return;
            
if (m_theTreeView.SelectedNode != null)
            {
                 
if (m_cbChildNode.Checked)
                {
                    SPNavigationNode selectedNode = GetCurrentNavigationNode(m_theTreeView.SelectedNode.Text, m_theTreeView.SelectedNode.Value, m_theWeb.Navigation.TopNavigationBar);
                      
if (selectedNode != null)
                     {
                          selectedNode.Children.AddAsLast(
new SPNavigationNode(m_txtChildTitle.Text.Trim(),
                              m_txtChildUrl.Text.Trim()));
                         m_theWeb.Update();
                         SPUtility.Redirect(
this.Context.Request.Url.AbsolutePath, SPRedirectFlags.Static, this.Context);
                     }
                 }
                 
else {
                    m_theWeb.AllowUnsafeUpdates =
true;
                    SPNavigationNode newNode =
new SPNavigationNode(m_txtChildTitle.Text.Trim(), m_txtChildUrl.Text.Trim());
                     m_theWeb.Navigation.TopNavigationBar.AddAsLast(newNode);
                     m_theWeb.Update();
                      SPUtility.Redirect(
this.Context.Request.Url.AbsolutePath, SPRedirectFlags.Static, this.Context);    
                 }
             }
         }

Following is the code snippet to update the existing and current selected node.

private void m_btnUpdate_Click(object sender, EventArgs e)
        {
            SPNavigationNode previousNode =
null;
            SPNavigationNode parentNode =
null;
            
if (m_theTreeView.SelectedNode != null)
            {
                m_theWeb.AllowUnsafeUpdates =
true;
                SPNavigationNode node = GetCurrentNavigationNode(m_theTreeView.SelectedNode.Text,
                    m_theTreeView.SelectedNode.Value, m_theWeb.Navigation.TopNavigationBar, ref previousNode,ref parentNode);
                 
if (node != null)
                {
                    node.Title = m_txtTitle.Text.Trim();
                    node.Url = m_txtUrl.Text.Trim();
                     node.Update();
                     m_theWeb.Update();
                      SPUtility.Redirect(
this.Context.Request.Url.AbsolutePath, SPRedirectFlags.Static, this.Context);
                 }
             }
         }

Following is the code snippet to delete an existing and current selected node.

private void m_btnDelete_Click(object sender, EventArgs e)
        {
            SPNavigationNode node =
this.GetCurrentNavigationNode(m_theTreeView.SelectedNode.Text, m_theTreeView.SelectedNode.Value, m_theWeb.Navigation.TopNavigationBar);
             
if (node != null)
            {
                 node.Delete();
                 m_theWeb.Update();
                 SPUtility.Redirect(
this.Context.Request.Url.AbsolutePath, SPRedirectFlags.Static, this.Context);
             }
        }

Steps to deploy the solution

Following are the steps to deploy the solution to the development server.

  1. Build the project.

  2. After successful product build, right click on project name in Solution Explorer and from WSPBuilder click Build WSP.

  3. After that, again right click project name, and from WSPBuilder click Deploy.

  4. This will deploy your solution to the development server.

  5. Now navigate to your desired SharePoint site, and activate the feature.

Steps to deploy the solution (.wsp) file on other SharePoint servers

  1. Build the project.

  2. After successful project build, right click on project name in Solution Explorer and from WSPBuilder click Build WSP.

  3. After that, open your project folder, and find the .wsp file. Generally, the name of the .wsp file is based on the project name.

  4. Copy that .wsp file to the desired SharePoint Server.

  5. Open command prompt.

  6. Navigate to the following Path:c:\Program Files\Common Files\Microsoft Shared\web server extensions\12\bin

  7. Now execute stsadm -o addsolution -filename <<Path of the .wsp file>>.

  8. Now opne SharePoint 3.0 Central Administration.

  9. Go to Operations.

  10. There from the "Global Configuration" group, select "Solution management".

  11. There click on the link with your deployed .wsp file.

  12. On the Solution Properties page, click Deploy Solutio from top toolbar.

  13. On the Deploy Solution page, in the "Deploy To?" section, select your desired web application of leave as it is.

  14. Click Ok. This will deploy your solution.

Now, when you add child nodes, they are displayed on the top navigation bar of the site with its parent node. To display the chid node below the parent node just like hierarchical menu you need to do some changes in the master page of the site.

Open your site in SharePoint Designer.

Open the default.master from _catelogs/masterpage.

Split the view to see the HTML and design of the master page.

On the design select the top navigation bar. This will select the SharePoint:AspMenu tag in HTML view.

Look for the property name StaticDisplayLevels and change is value to 1.

Look for the property name MaximumDynamicDisplayLevels and set it to your desired value like 2 or 3.

Now, when the child nodes are added to the top level nodes, the will be display like below.

When you create any sub site, it inherits the top navigation from is parent. To stop inheriting and to create its own top navigation you have to go to Site Setting of sub site. Then go to Top Link Bar page from Look and Feel group. There you will find the tool bar having link button with text "Stop Inheriting Links". By clicking this it will stop the inheriting the parent top navigation and provide you the interface to create new links.

Now enable this feature for this site and manage the top navigation for this site as well.

At the end...

So, this way we can implement the custom top navigation manager and can change the way the top navigation menu and its items. Hope this article will be useful to the developers who require this type of facility in their SharePoint sites. Limitation of this implementation is that, user can't change the order of the nodes. Also, when you deactivate the feature, it will not remove any nodes which are created through this top navigation manager.

Source code

You can download the fully working code from below. The code is written in C# and Visual Studio 2008 and using WSP Builder Project template.

Custom Top Navigation Manager

By Jatin Prajapati   Popularity  (3496 Views)
Picture
Biography - Jatin Prajapati
I think, most of the people are interested only in answers so no Biography provided... Want know more just write me at jatin.prajapati.er@gmail.com