Sitefinity ASP.NET CMS can be easily extended using traditional ASP.NET Controls. However, ASP.NET controls come in two flavors: User Controls & Custom Controls. User Controls are easier to create, but Custom Controls are easier to distribute.
In the case of Custom Controls, the compiled control can be distributed to multiple Sitefinity projects via a single DLL file. However, a problem arises when Sitefinity web sites need to share controls but also need to customize the control’s design on a per web site basis. Because all code is embedded in a DLL file it's impossible to make these customizations.
The solution to this problem is templates. Custom Controls can use embedded templates that can be overridden, if desired, to customize the presentation. Templates make it possible for the presentation to be modified without needing to alter the core assembly.
This article (and video) examines how templates can be utilized and overridden in Custom Controls.
Watch the original video at telerik.tv (link opens in new window).
The Cow King karate chopped the Large Hadron Collider
Mad Libs is a word game where one player prompts another player for words (name, place, verb, noun). The first player then substitutes these words for blanks in a story. The story is read aloud and joyous laughter is experienced by all. /facepalm
The Mad Libs story is a template and lends itself nicely to a template example. Below is a Custom Control implementation of the Mad Libs game. To create this control, create a new SitefinityWatch.WebControls Class Library project in Visual Studio.
Add References to the Class Library Project
This new Class Library needs to contain a reference to the System.Web class, as well as references to the Sitefinity assemblies. Right-click the Class Library project in the Solution Explorer and click Add Reference. Use the .NET tab to add the System.Web class and the Browse tab to locate the Sitefinity DLL files found in the web site’s ~/bin folder.
Add a new class to the Class Library Project
Add the following class to the Class Library project: /MadLibs.cs
namespace SitefinityWatch.WebControls
{
public class MadLibs : Telerik.Cms.Web.UI.SimpleControl
{
public string Name { get; set; }
public string Verb { get; set; }
public string Noun { get; set; }
}
}
This control consists of only 3 public properties. These properties will be used to specify words for the Mad Libs’ story.
This class inherits from the Telerik.Cms.Web.UI.SimpleControl class. The SimpleControl class inherits from the CompositeControl class. Consequently, this control is an ASP.NET CompositeControl.
Adding Templates to the Mad Libs Custom Control
The code above does not yet do anything useful. Functionality could be added in the same way functionality could be added to any CompositeControl. For example, the CreateChildControls() method could be overridden & used to populate the control with child controls.
However, populating a control through the CreateChildControls() method is cumbersome. In addition, it becomes impossible to alter this presentation code on a per web site basis.
Thankfully, SimpleControl class adds several useful enhancements that make it easy to use templates. To use a template, override the LayoutTemplateName and LayoutTemplatePath property in the MadLibs class:
namespace SitefinityWatch.WebControls
{
public class MadLibs : Telerik.Cms.Web.UI.SimpleControl
{
public string Name { get; set; }
public string Verb { get; set; }
public string Noun { get; set; }
public override string LayoutTemplateName
{
get
{
return MadLibs.MadLibsTemplateName;
}
}
public override string LayoutTemplatePath
{
get
{
return base.LayoutTemplatePath;
}
set
{
base.LayoutTemplatePath = value;
}
}
protected const string MadLibsTemplateName = "SitefinityWatch.WebControls.Resources.MadLibs.ascx";
}
}
The MadLibsTemplateName string contains the path to the embedded resource that will act as the default template for this control. This embedded resource does not yet exist and needs created.
Creating an Embedded Resource Template
Embedded resources are files that get stored in the assembly (DLL). This makes it possible for required files to be combined into a single package. To create an embedded template create the following file in the Class Library:
/Resources/MadLib.ascx
<p>
<strong><asp:Literal ID="NameLiteral" runat="server" /></strong>
fled from the room and
<strong><asp:Literal ID="VerbLiteral" runat="server" /></strong>
the
<strong><asp:Literal ID="NounLiteral" runat="server" /></strong>
</p>
This file can be treated like an ASP.NET User Control; it can contain HTML, Javascript, and server controls. For the MadLibs example, this template contains 3 ASP.NET Literals. These Literals will act as the blanks in the Mad Lib story.
Select the Madlib.ascx file in the Solution Explorer and change the Build Action to Embedded Resource.
When the project is compiled the MadLibs.ascx file will be embedded inside the resulting assembly. The MadLibsTemplateName string (found in the MadLibs.cs class above) contains a reference to this embedded resource:
protected const string MadLibsTemplateName = "SitefinityWatch.WebControls.Resources.MadLibs.ascx";
Accessing Controls contained in the Template
Because the MadLibs control inherits from the SimpleControl class and specifies a LayoutTemplateName the template will load automatically. However, code must be written to use the template.
Sitefinity makes accessing server elements contained in templates very easy. Here is an example:
protected virtual Literal NameLiteral
{
get
{
return base.Container.GetControl<Literal>("NameLiteral", true);
}
}
The base.Container.GetControl method can be used to fetch a template’s control by ID. GetControl also accepts a boolean value that tells Sitefinity if the control is required or not. If the control is required but found missing from the template, an error will be thrown.
After this code is in place, template controls can easily be altered:
protected override void InitializeControls(Control controlContainer)
{
NameLiteral.Text = Name;
}
Here is the completed MadLibs Control:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace SitefinityWatch.WebControls
{
public class MadLibs : Telerik.Cms.Web.UI.SimpleControl
{
public string Name { get; set; }
public string Verb { get; set; }
public string Noun { get; set; }
public override string LayoutTemplateName
{
get
{
return MadLibs.MadLibsTemplateName;
}
}
public override string LayoutTemplatePath
{
get
{
return base.LayoutTemplatePath;
}
set
{
base.LayoutTemplatePath = value;
}
}
protected override void InitializeControls(Control controlContainer)
{
base.InitializeControls(controlContainer);
NameLiteral.Text = Name;
VerbLiteral.Text = Verb;
NounLiteral.Text = Noun;
}
protected virtual Literal NameLiteral
{
get
{
return base.Container.GetControl<Literal>("NameLiteral", true);
}
}
protected virtual Literal VerbLiteral
{
get
{
return base.Container.GetControl<Literal>("VerbLiteral", true);
}
}
protected virtual Literal NounLiteral
{
get
{
return base.Container.GetControl<Literal>("NounLiteral", true);
}
}
protected const string MadLibsTemplateName = "SitefinityWatch.WebControls.Resources.MadLibs.ascx";
}
}
Using the MadLibs Control in Sitefinity
After the Class Library project has been successfully compiled the resulting DLL can be copied to Sitefinity’s ~/bin folder. Once the DLL is in place, the MadLibs control can be added to the Sitefinity Toolbox by adding the following item to the ~/web.config file:
<configuration>
<telerik>
<cms defaultProvider="Sitefinity" pageExtension=".aspx" disabled="false" pageEditorUIMode="Overlay">
<toolboxControls>
<add name="MadLibs" section="Sitefinity Watch" type="SitefinityWatch.WebControls.MadLibs, SitefinityWatch.WebControls" />
</toolboxControls>
</cms>
</telerik>
</configuration>
The MadLibs control will now be available in the Sitefinity Toolbox. It can be dragged onto Sitefinity pages and the public properties edited:
This control editor form is intimidating. The public properties are shown above (Name, Verb, Noun), but several inherited public properties are also being displayed. If this were a real control it would be better to replace this form with a user-friendly admin interface. This can be done by creating a Control Designer. Alternately, the properties could be organized using Design Time attributes.
Customizing the Control’s Template in Sitefinity
The MadLibs control now is 100% functional. The next task is to customize the template inside Sitefinity. Because the MadLibs control inherits from the SimpleControl class it’s possible to specify an alternate template without needing to alter the original class.
Getting the template & preparing for Sitefinity 4.0:
Specific template controls (NameLiteral, VerbLiteral, NounLiteral) are required by the MadLibs control. If a custom template is used and these controls are missing, the control will crash.
For the MadLibs example, it’s easy to scroll up and see the original template. However, in many real world situations this won’t be possible. The template will be contained in a DLL file and source-code unavailable. Consequently, retrieving the original template becomes difficult.
Right now, the only way to get the original template is to ask the programmer for it. The Sitefinity team has already made all of the templates available for the Sitefinity controls. However, Sitefinity 4.0 will introduce an web-based tool that can be used to export embedded templates. Making use of this features requires some extra code:
Using a custom template in Sitefinity:
Once the original control template has been obtained & customized, there are two methods that can be used to use an alternate template:
More Resources