The SelectedTemplate and duplicate code

Posted on November 11, 2009 by Frederik Vig in EPiServer

The SelectedTemplate is used in the MenuList and PageList EPiServer web controls. It is a template used for displaying selected items in navigation lists. This is a nice template to have, but sometimes it is an overkill to use it. Say when you only need to add a class of selected or active (which happened to me today).

The problem

<ul class="nav">
	<li>
		<a href="#">
			<span class="l"></span><span class="c">PageName</span><span class="r"></span>
		</a>
	</li>
	<li>
		<a href="#" class="active">
			<span class="l"></span><span class="c">PageName</span><span class="r"></span>
		</a>
	</li>
</ul>

This is a simple navigation list, but as you can see we have two span tags inside the anchors (this is a technique used when you need to use more than one background image). So we cannot use the EPiServer:Property control that we would use normally.

<EPiServer:Property PropertyName="PageLink" runat="server" />

The normal solution

Instead we’re using a combination of HTML and data binding syntax.

<ItemTemplate>
	<li>
		<a href="<%# Container.CurrentPage.LinkURL %>">
			<span class="l"></span><span class="c"><%# Container.CurrentPage.Property["PageName"].ToWebString() %></span><span class="r"></span>
		</a>
	</li>
</ItemTemplate>
<SelectedTemplate>
	<li>
		<a href="<%# Container.CurrentPage.LinkURL %>" class="active">
			<span class="l"></span><span class="c"><%# Container.CurrentPage.Property["PageName"].ToWebString() %></span><span class="r"></span>
		</a>
	</li>
</SelectedTemplate>

This will work fine, but is not good practice, since we now have duplicated the same code in both templates, only adding class=”active” to the SelectedTemplate.

Solution

We’re now going to update the code to only use the ItemTemplate, and add a little logic for checking if the item should be selected or not.

<ItemTemplate>
	<li>
		<a href="<%# Container.CurrentPage.LinkURL %>" <%# SelectedCssClass(Container.CurrentPage, "active") %>>
			<span class="l"></span><span class="c"><%# Container.CurrentPage.Property["PageName"].ToWebString() %></span><span class="r"></span>
		</a>
	</li>
    </ItemTemplate>

The SelectedCssClass method lives in our code-behind file and looks like this:

protected string SelectedCssClass(PageData page, string cssClass)
{
	var result = string.Empty;
	if (page == null || page.PageLink.ID < 1)
	{
		return result;
	}
 
	if (page.IsSelected(CurrentPage))
	{
		result = string.Format("class=\"{0}\"", cssClass);
	}
 
	return result;
}

As you can see I’m using an extension method (from the EPiCode.Extensions project) in my if statement. This method simply takes the CurrentPage and checks if it, or any of its parents, match the page that is being data binded (same thing as the SelectedTemplate does).

By adding this logic to our code-behind (or a helper class), instead of using the SelectedTemplate just for this little thing, we make it much easier for us or (even more important) the next developer to change and update the navigation list. We’ve eliminated a code smell :).

Related Posts: