I have a page template that dynamically renders all the datasource items that are in its Components folder. The way the page works is that there are no components in the placeholder settings on the page except for the ContentPage rendering, and the ContentPage rendering dynamically displays every datasource item in the local Components folder by assigning all of the datasource items to a ListView; within the ListView is a every possible sublayout, and it determines which sublayout to make visible while leaving the rest of them not visible. (Note that I didn't create this page, it already existed when I took over working on this site). An example of the code:
<%@ Control Language="C#" AutoEventWireup="True" CodeBehind="~/CustomSources/SharedLayouts/ContentPageBranch.cs" Inherits="Project.SC.CustomSources.SharedLayouts.ContentPageBranch" %>
<div class="content-page-branch">
<asp:ListView runat="server" ID="contentItemList" OnItemDataBound="TeaserDataBound">
<ItemTemplate>
<sc:Sublayout id="phIntroduction" runat="server" Visible="false" Path="/layouts/Common/Modules/page editor/Content/Introduction.ascx" />
<sc:Sublayout id="phSpotlight" runat="server" Visible="false" Path="/layouts/Common/Modules/page editor/Content/Spotlight.ascx" />
<sc:Sublayout id="phImage" runat="server" Visible="false" Path="/layouts/Common/Modules/page editor/Content/Image.ascx" />
<sc:Sublayout id="phDownloadList" runat="server" Visible="false" Path="/layouts/Common/Modules/page editor/Content/DownloadList.ascx" />
</ItemTemplate>
</asp:ListView>
</div>
protected void Page_Load(object sender, EventArgs e)
{
try
{
string ds = ((Sitecore.Web.UI.WebControls.Sublayout)this.Parent).DataSource;
item = BranchesHelper.GetContextItem(ds);
ListView lvContentItemList = FindControl(LISTVIEW_CONTENT_ITEMLIST) as ListView;
List<Item> dsList = BranchesHelper.GetItems(Consts.FOLDERID_MAIN, this);
itemsInFolderCount = dsList.Count;
lvContentItemList.DataSource = dsList;
lvContentItemList.DataBind();
}
catch (Exception ex)
{
LogManager.LogError("Content Page Branch", "Failed to load Modules", ex);
if (Util.Helper.AllowThrowException)
{
throw;
}
}
}
protected void TeaserDataBound(object sender, ListViewItemEventArgs args)
{
try
{
ListViewDataItem di = args.Item as ListViewDataItem;
if (di != null)
{
item = BranchesHelper.SetLanguage(di);
BranchesHelper.DisableAllPanelsAndPlaceHoldersByPage(this.Page);
if (item != null && item.Exists())
{
if (ListViewCounter == 0 && !string.IsNullOrEmpty(item.Parent.Parent[Consts.FIELDS_HIDE_LEFTHAND]) && item.Parent.Parent.Fields[Consts.FIELDS_HIDE_LEFTHAND].Value == Consts.VALUE_CHECKBOX_ACTIVE)
{
CreateOverviewLink(args);
}
positionInFolder++;
ListViewCounter++;
bool isScopeLayout = BranchesHelper.BindScopeLayout(item,false,args,PLACEHOLDER_SCOPE_LAYOUTS,positionInFolder,Consts.FOLDERID_MAIN);
if (!isScopeLayout)
{
string templateId = item.TemplateID.Guid.ToString().ToUpper();
switch (templateId)
{
case Consts.TEMPLATEID_INTRODUCTION:
InitIntroduction(args);
break;
case Consts.TEMPLATEID_TEASER:
InitTeaser(args);
break;
case Consts.TEMPLATEID_CONTENTBLOCK:
InitContentBlock(args);
break;
default:
if (templateId == Consts.TEMPLATEID_MODULE_OVERVIEW)
{
InitModuleOverview(args);
}
else if (templateId == Consts.TEMPLATEID_TEASER_GROUP)
{
InitSublayout(args, PLACEHOLDER_TEASER_GROUP, positionInFolder, Consts.FOLDERID_MAIN);
}
break;
}
}
positionSlider = 0;
}
}
}
catch (Exception ex)
{
LogManager.LogError("Content Page Branch", "Failed to load DataItem", ex);
if (Util.Helper.AllowThrowException)
{
throw;
}
}
}
private void InitIntroduction(ListViewItemEventArgs args)
{
isIntroduction = true;
InitSublayout(args, PLACEHOLDER_INTRODUCTION, positionInFolder, Consts.FOLDERID_MAIN);
}
public static void InitSublayout(ListViewItemEventArgs args, Sublayout sublayout, int position, string folderId = null, Dictionary<string, string> additionalParameters = null)
{
try
{
if (args != null && args.Item != null)
{
Item item = args.Item.DataItem as Item;
if (item != null)
{
if (sublayout != null)
{
sublayout.Visible = true;
sublayout.DataSource = item.ID.ToString();
}
}
}
}
catch (Exception ex)
{
}
}
There's a couple steps I've left out, but you can see the basic idea-- all of the sublayouts are by default not visible, and the switch statement will make the correct sublayout visible.
HOWEVER, even when the sublayouts are not visible, they are still rendering. I do not think this was happening in Sitecore 6.5, but once we upgraded to 8.2, I noticed the issue because all of the sublayouts log an error when they render with no datasource; once the upgrade happened, I discovered that thousands of errors were being logged, and it was because every time these pages loaded, every single sublayout was trying to render even when they were not visible and had no datasource.
public partial class Spotlight : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
item = ContentHelper.GetContextItem(((WebControl)Parent).DataSource);
if (item == null)
{
Log.Error("Could not find Spotlight datasource item. Containing page Item: "
+ Sitecore.Context.Item.Name
+ ", Containing page Item ID: "
+ Sitecore.Context.Item.ID.ToString()
+ ", Rendering: "
+ ((WebControl)Parent).RenderingName
+ ", Rendering ID: "
+ ((WebControl)Parent).RenderingID
, this);
return;
}
InitSpotlight();
}
}
This is causing performance issues; these particular pages take more time to load than any other pages on the site, sometimes upwards of 10 seconds. So what would be the best way to handle this? I tried wrapping every sublayout in a conditional like this, but it still renders every time:
<% if (isIntroduction)
{ %>
<sc:Sublayout id="phIntroduction" runat="server" Visible="false" Path="/layouts/Common/Modules/page editor/Content/Introduction.ascx" />
<% } %>