Sitecore : Top Navigation

This is my first Sitecore CMS post, so I thought I will start with something very simple, what could be more simpler than ‘Top Navigation’

Sitecore gives you the flexibility to render items by XSLT or by .NET UserControls.

I prefer using .NET Controls over XSLT for various reasons

1. XSLT are easy to implement and fast but difficult to maintain when you have to introduce complex logic for navigation (like if user is logged in or not)
2. XSLT are difficult to debug (imagine going through 3 to 4 foreach loops!)
3. XSLT are so old, I feel like working in 90s (but people still use it)

Anyways, I will implement a very simple top navigation with a repeater in a .NET UserControl which will take top childrens of ‘Home’ Item/Node and render them
as top navigation

Here is the code for repeater (pretty standard)

<asp:Repeater ID="RepeaterTopNavigation" runat="server" OnItemDataBound="RepeaterTopNavigation_ItemDataBound">
<HeaderTemplate>
<ul>
<li><a href="/home.aspx">Home</a></li>
</HeaderTemplate>

<ItemTemplate>
<li>
<asp:HyperLink ID="HyperLinkTopNavigation" runat="server"></asp:HyperLink>
</li>
</ItemTemplate>

<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>

And here is the code behind for the repeater

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Sitecore.Data.Items;
using Sitecore.Links;

namespace SampleSite.Controls
{
public partial class TopNavigation : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
//get the home item, this is hardcoded but you can define it in web.config
Item home = Sitecore.Context.Database.GetItem("/sitecore/content/home");
//get all children from home using Sitecore API
Item[] children = home.Children.ToArray();
//Bind the children to repeater
RepeaterTopNavigation.DataSource = children;
RepeaterTopNavigation.DataBind();

}

public void RepeaterTopNavigation_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
//gets the current data item from RepeaterItemEventsArgs and cast it as a Sitecore Item
Item currentItem = (Item)e.Item.DataItem;

//check if it is not null, safety first
if (currentItem != null)
{

//check if it is coming from Item or Alternating Item template
if (e.Item.ItemType == ListItemType.Item || 
          e.Item.ItemType == ListItemType.AlternatingItem)
{

//Find the HyperLink control that has been defined in repeater
HyperLink topNavigation = (HyperLink)e.Item.FindControl("HyperLinkTopNavigation");
//Use Sitecore API to get the link to the Item and upadte the href property of link
topNavigation.NavigateUrl = LinkManager.GetItemUrl(currentItem);
//Assign name to the link
topNavigation.Text = currentItem.Name;

}
}
}
}
}

Explanation

1. Get the home Item
2. Get the children of home Item as array
3. Bind them to repeater
4. For OnItemDataBound, cast the DataItem as Sitecore Item and update the HyperLink property for each

Drop the control on your main layout and check for any build errors.

Thats it!

5 thoughts on “Sitecore : Top Navigation

  1. I agree with your choice of favoring UserControls over XSLT’s. In fact, the only component that’s easier to develop using XSLT’s are the infamous hierahical left menu. And even so, I perfer to develop it using usercontrols as it gives me greater extendability.

    http://briancaos.wordpress.com/2011/01/25/using-usercontrols-instead-of-xslt-in-sitecore-projects/

    http://briancaos.wordpress.com/2011/08/03/creating-a-tree-like-left-menu-in-sitecore-using-usercontrols-and-c/

  2. Hi Naveed,

    Thanks for this solution. I’m trying to integrate it into my sitecore website but I’m having some problems. I get a System.NullReferenceException: Object reference not set to an instance of an object. error when I publish the site.

    The source error is:

    Line 45: HyperLink topNavigation = (HyperLink)e.Item.FindControl(“HyperLinkTopNavigation”);
    Line 46: //Use Sitecore API to get the link to the Item and upadte the href property of link
    Line 47: topNavigation.NavigateUrl = LinkManager.GetItemUrl(currentItem);
    Line 48: //Assign name to the link
    Line 49: topNavigation.Text = currentItem.Name;

    ———————-

    The stack trace is:

    [NullReferenceException: Object reference not set to an instance of an object.]
    Layouts.Topnavigation.TopnavigationSublayout.RepeaterTopNavigation_ItemDataBound(Object sender, RepeaterItemEventArgs e) in c:\inetpub\wwwroot\Infotech\Website\layouts\TopNavigation.ascx.cs:47
    System.Web.UI.WebControls.Repeater.CreateControlHierarchy(Boolean useDataSource) +692
    System.Web.UI.WebControls.Repeater.OnDataBinding(EventArgs e) +67
    Layouts.Topnavigation.TopnavigationSublayout.Page_Load(Object sender, EventArgs e) in c:\inetpub\wwwroot\Infotech\Website\layouts\TopNavigation.ascx.cs:26
    System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +24
    System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +41
    System.Web.UI.Control.OnLoad(EventArgs e) +131
    System.Web.UI.Control.LoadRecursive() +65
    System.Web.UI.Control.LoadRecursive() +190
    System.Web.UI.Control.LoadRecursive() +190
    System.Web.UI.Control.LoadRecursive() +190
    System.Web.UI.Control.LoadRecursive() +190
    System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2427

    —————————-

    My code is:

    Home

    —————————–

    My code behind is:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using Sitecore.Data.Items;
    using Sitecore.Links;

    namespace Layouts.Topnavigation {

    ///
    /// Summary description for TopnavigationSublayout
    ///
    public partial class TopnavigationSublayout : System.Web.UI.UserControl
    {
    protected void Page_Load(object sender, EventArgs e)
    {
    //get the home item, this is hardcoded but you can define it in web.config
    Item home = Sitecore.Context.Database.GetItem(“/sitecore/content/home”);
    //get all children from home using Sitecore API
    Item[] children = home.Children.ToArray();
    //Bind the children to repeater
    RepeaterTopNavigation.DataSource = children;
    RepeaterTopNavigation.DataBind();

    }

    public void RepeaterTopNavigation_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
    //gets the current data item from RepeaterItemEventsArgs and cast it as a Sitecore Item
    Item currentItem = (Item)e.Item.DataItem;

    //check if it is not null, safety first
    if (currentItem != null)
    {

    //check if it is coming from Item or Alternating Item template
    if (e.Item.ItemType == ListItemType.Item ||
    e.Item.ItemType == ListItemType.AlternatingItem)
    {

    //Find the HyperLink control that has been defined in repeater
    HyperLink topNavigation = (HyperLink)e.Item.FindControl(“HyperLinkTopNavigation”);
    //Use Sitecore API to get the link to the Item and upadte the href property of link
    topNavigation.NavigateUrl = LinkManager.GetItemUrl(currentItem);
    //Assign name to the link
    topNavigation.Text = currentItem.Name;

    }
    }
    }
    }
    }

    ————

    I would appreciate any help I could get.

    thank you,

    Perplexed

    1. Sorry, for the late reply, I hope this has been resolved, most probably a typo in .ascx file for the control “HyperLinkTopNavigation”

Leave a reply to Thusitha Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.