Get the Sitecore Sublayout from your .aspx page (Usercontrol)

How do you get the Sitecore Sublayout from a Usercontrol? A Sitecore Sublayout (Sitecore.Web.UI.WebControls.Sublayout) is a container for your Usercontrol (.ascx) page. Therefore the Sublayout is retrieved by typecasting the parent to a Sublayout:

using Sitecore.Web.UI.WebControls;

Sublayout thisSublayout = (Parent as Sublayout);

Having the Sublayout in hand enables you to read the Sublayout data, for example the “datasource” field. The datasource field can be used to alter which item the Sublayout should render. You can apply a datasource to your sublayout directly, telling the userControl (.aspx page) to render a different item than the current item (Sitecore.Context.Item).

In one of my recent projects (for Sitecore Foundry, but the code works for Sitecore 5 and Sitecore 6 as well) I inherited from this base class instead of the System.Web.UI.UserControl. The class is very simple. It gives me the Sitecore item as stated in the datasource, or the current item if the datasource item is not set:


using Sitecore.Data.Items;
using Sitecore.Web.UI.WebControls;

namespace MyProject.MyNameSpace
{
  /// <summary>
  /// This class contains the CurrentContextItem function
  /// which allows the system to use
  /// the datasource property on sublayouts.
  /// </summary>
  public class SublayoutBaseClass : System.Web.UI.UserControl
  {
    /// <summary>
    /// Gets the current context item.
    /// </summary>
    /// <value>The current context item.</value>
    protected Item CurrentContextItem
    {
      get
      {
        Sublayout thisSublayout = (Parent as Sublayout);
        if (thisSublayout == null)
          return Sitecore.Context.Item;
        if (string.IsNullOrEmpty(thisSublayout.DataSource))
          return Sitecore.Context.Item;
        string dataSource = thisSublayout.DataSource;
        Item dataSourceItem = Sitecore.Context.Database.GetItem(dataSource) ??
                              Sitecore.Context.ContentDatabase.GetItem(dataSource);
        if (dataSourceItem == null)
          return Sitecore.Context.Item;
        return dataSourceItem;
      }
    }
  }
}

Applying datasource to sublayouts on Sitecore items

In Sitecore you can apply a datasource to a sublayout when adding it to a template/item. But the datasource is not automatically used. Your context will not change to the item specified in the datasource.
The datasource is therefore not used as a context change – but it can be. All you need is to use the brilliant code provided by Alexey Rusakov and alter it a bit.

Here is my thoughts: I apply a sublayout to a page. I then alter the datasource because I want the sublayout to get it’s data from another item than the current one.
First I have rewritten the code from Alexey into a function that will return the RenderingDefinition from a specific sublayout on the current item for the current context. All you need is the path to the sublayout in question:

using Sitecore.Layouts;
using Sitecore.Data.Items;

private RenderingDefinition GetRenderingDefinition(string path)
{
  // Get the Layout definition from the current item
  string rend = Sitecore.Context.Item.Fields["__renderings"].Value;
  LayoutDefinition layout = LayoutDefinition.Parse(rend);
  // Get the current device definition
  DeviceDefinition device = layout.GetDevice(Sitecore.Context.Device.ID.ToString());
  // Get the sublayout to find
  Item mySublayout = Sitecore.Context.Database.Items[path];
  // Get the definition for the sublayout
  RenderingDefinition rendering = device.GetRendering(mySublayout.ID.ToString());
  return rendering;
}

I can then use the RenderingDefinition to get the item that the datasource is pointing to. If there is no datasource it means that no datasource have been applied and I’ll use the current item:

private Item GetCurrentItem()
{
  RenderingDefinition def = GetRenderingDefinition("/sitecore/layout/Sublayouts/MySubLayout");
  if (def.Datasource == String.Empty)
    return Sitecore.Context.Item;
  Item dataSourceItem = Sitecore.Context.Database.GetItem(def.Datasource);
  Sitecore.Diagnostics.Assert.IsNotNull(dataSourceItem, "Could not find datasource item at " + def.Datasource);
  return dataSourceItem;
}

In my codebehind for the sublayout I use the item returned by the GetCurrentItem() function instead of the Sitecore.Context.Item, and voila! I have my context change.

BTW: The RenderingDefinition contains much more than the datasource. You can also get the parameters, placeholder and caching informations.
Subnote: Alexey Rusakov describes on his blog that in Sitecore 6 you can use the Attributes["sc_parameters"] to get the parameters for a sublayout. That’s true, but the parameters does not contain the datasource, only the parameters.

Follow

Get every new post delivered to your Inbox.

Join 92 other followers