Return to doc.sitecore.com

Building Web Controls - Part 2 (simple menu)

1.  Control Tag

The easiest way to build a custom web control is to derive from the Sitecore.Web.UI.WebControl class. This is not a requirement, but it will make things easier, as this class includes a lot of support methods for data access, rendering, and so on.

 

In the following sections you will learn how to build a Menu control in C#. The control will display the children of a specific Item as a series of links.

 

The control can be used in ASPX or ASCX by including a tag

 

<ctl:menu runat="server"/>

 

The ASCX file needs to reference the DLL containing the control. Assuming that the control is compiled into mycontrols.dll, a valid ASCX page would be

 

<%@ Control Language="c#" AutoEventWireup="true" 
    TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>

<%@ Register TagPrefix="ctl" 
    Namespace="Articles.API.Webcontrols"
    Assembly="mycontrols" %>

 

<ctl:Menu_part1 runat="server" />

 

The following class will serve as the skeleton for the control

1.1.  Skeleton for control

using System.Web.UI;

namespace Articles.API.Webcontrols
{
  
/// <summary>
  
/// Reference Sitecore.Kernel, System.Web, System
  
/// </summary>

  public class Menu_part1 : Sitecore.Web.UI.WebControl
  
{
    
protected methods
  }

}

2.  Implementing DoRender Method

The only method that must be implemented is DoRender which is abstract in the base class WebControl.

 

The job of the DoRender method is to render the control as HTML to the output object.

 

As we want to render a list of child Items, the first task is to get hold of the Item the menu control points to (we can call this the root item).

 

The root Item is specified by using the DataSource property of the control (inherited from WebControl). In an ASPX file, this will look like

  

<ctl:Menu_part1 runat="server" datasource="/sitecore/content/home"/>

 

Given this definition, the menu control should show a clickable list of the children of the Item with the path "/sitecore/content/home".

 

It is not mandatory to specify the root Item. The following definition is also valid. 

 

<ctl:Menu_part1 runat="server"/>

 

In this case, the root Item will be set to the current Item in the context (i.e. Sitecore.Context.Item).

 

For instance, if you request the web page /products/chair.html, the root Item of the menu would be the Item with the relative path "/products/chair".

 

To get the root Item programmatically, use the GetItem()  method derived from WebControl.

 

After retrieving the Item, children can be iterated using the Children property of the Item class.

 

To begin rendering, the following implementation of the menu will simply list the names of child Items.

2.1.  Menu listing child names

using System.Web.UI;

namespace Articles.API.Webcontrols
{
  
/// <summary>
  
/// Read about this web control in the article on
  
/// sdn.sitecore.net web site.
  
///
  
/// Reference Sitecore.Kernel, System.Web, System
  
/// </summary>

  public class Menu_part1 : Sitecore.Web.UI.WebControl
  
{
    
protected methods
  }

}

3.  GetFriendlyUrl Method

To insert actual links, the helper method GetFriendlyUrl can be used. Also, to show user friendly, language versioned Item names, the DisplayName property should be used instead of Name.

 

This results in the first working menu is shown below.

3.1.  Source - Menu with links

protected override void DoRender(HtmlTextWriter output)
{
  Sitecore.Data.Items.Item rootItem
=
    
this.GetItem();

  
if (rootItem!=null)
  
{
    Sitecore.Collections.ChildList children
=
      rootItem.Children;

    
foreach (Sitecore.Data.Items.Item child in children)
    
{
      
string url =
        child.Paths.GetFriendlyUrl();

      output.RenderBeginTag(HtmlTextWriterTag.Div);
      output.AddAttribute(HtmlTextWriterAttribute.Href, url);
      output.AddAttribute(HtmlTextWriterAttribute.Style,
"font-weight:bold");
      output.RenderBeginTag(HtmlTextWriterTag.A);
      output.Write(child.DisplayName);
      output.RenderEndTag();
// end A tag
      output.RenderEndTag(); // end Div tag
    }

  }

}

4.  Custom Properties

The control can be extended with custom properties. For instance, to be able to control the visual style of links, you can add a LinkStyle property.

4.1.  Source - Full Menu

using System.Web.UI;

namespace Articles.API.Webcontrols
{
  
/// <summary>
  
/// Read about this web control in the article on
  
/// sdn.sitecore.net web site.
  
///
  
/// Reference Sitecore.Kernel, System.Web, System
  
/// </summary>
  public class Menu_part1: Sitecore.Web.UI.WebControl
  {

  
#region Variables

  
private string m_linkStyle; // Used for property

  
#endregion


  
#region Properties

  [Sitecore.Web.UI.WebControlProperty]
  
public string LinkStyle
  {
    
get
    {
      
return m_linkStyle;
    }
    
set
    {
      m_linkStyle
= value;
    }
  }

  
#endregion


  
#region protected methods

  
protected override void DoRender(HtmlTextWriter output)
  {
    Sitecore.Data.Items.Item rootItem
=
      
this.GetItem();

    
if (rootItem!=null)
    {
      Sitecore.Collections.ChildList children
=
        rootItem.Children;

      
foreach (Sitecore.Data.Items.Item child in children)
      {
        
string url =
          child.Paths.GetFriendlyUrl();

        output.RenderBeginTag(HtmlTextWriterTag.Div);
        output.AddAttribute(HtmlTextWriterAttribute.Href, url);
        output.AddAttribute(HtmlTextWriterAttribute.Style, LinkStyle);
        output.RenderBeginTag(HtmlTextWriterTag.A);
        output.Write(child.DisplayName);
        output.RenderEndTag();
// end A tag
        output.RenderEndTag(); // end Div tag
      }
    }
  }

  
#endregion
  }
}

5.  Using web control from aspx or ascx

The new property can be used in ASPX or ASCX in the following way, which will result in the bold menu style.

5.1.  Source - ASCX

<%@ Control Language="c#" AutoEventWireup="true"
TargetSchema
="http://schemas.microsoft.com/intellisense/ie5" %>
<%@ Register TagPrefix="ctl"
Namespace
="Articles.API.Webcontrols" Assembly="mycontrols" %>

<ctl:Menu_part1 runat="server"
  datasource
="/sitecore/content/home"
  LinkStyle
="font-weight:bold;" />