Update: New! We turned this concept into the first MVC based marketplace add-on for Sitefinity 5.1! Get the the ListBrowser with source from our store.
"Kendo UI is an HTML5, jQuery-based framework for building modern web apps. The framework features more than a dozen UI components, including a Grid and Chart, and all of the tools needed for a HTML5 app development, such as Data Binding, Templating, Drag-and-Drop API, and more."
Telerik's KendoUI has been around for a while and many of us got hands on the Beta last summer and I was really thrilled when I started playing around with it. I always pondered over the idea of using KendoUI in our Sitefinity projects instead of the RadControls due to the amount of resources that the latter require to be loaded in order to work decently.
In this series of posts, I am going to show you how we could leverage the different KendoUI components to display our Sitefinity content. KendoUI is a jQuery-based framework which runs on the client. What this means, is that we have to either use the REST API to get the Sitefinity content or we would have to develop server side controls based on Kendo components. The latter option sounds very pleasing to me and that is what we will try to accomplish in this series.
The first logical step that I thought about was to create a base class for all of the Kendo control that we are going to develop. This base class would take care of loading KendoUI's resources and expose the fundamental properties to be shared by all our controls.
That is how the base class looks like. Note that this is work in progress and this class will be enhanced in the next few posts.
public class KendoUIControlBase : SimpleView
{
#region Constants and Fields
private const string CSS_COMMON_URL = "~/Widgets/Kendo/Resources/Stylesheets/kendo.common.min.css";
private const string CSS_DEFAULT_URL = "~/Widgets/Kendo/Resources/Stylesheets/kendo.default.min.css";
private const string KENDOUI_JS_ALL_MIN = "~/Widgets/Kendo/Resources/JavaScript/kendo.all.min.js";
private string _theme = "default";
#endregion
#region Properties
private bool _includeKendoUIJavaScript = true;
/// <summary>
/// Determines whether to include the complete kendo UI JS file.
/// </summary>
public bool IncludeKendoUIJavaScript
{
get { return _includeKendoUIJavaScript; }
set { _includeKendoUIJavaScript = value; }
}
/// <summary>
/// Gets or sets the name of the theme to be used for this instance
/// </summary>
public string Theme
{
get { return _theme; }
set { _theme = value; }
}
#endregion
#region Overrides of SimpleView
/// <summary>
/// Initializes the controls.
/// </summary>
/// <remarks>
/// Initialize your controls in this method. Do not override CreateChildControls method.
/// </remarks>
protected override void InitializeControls(GenericContainer container)
{
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
Utils.AddCssLink(CSS_COMMON_URL);
Utils.AddCssLink(CSS_DEFAULT_URL);
if (IncludeKendoUIJavaScript)
{
Utils.AddJsLink(KENDOUI_JS_ALL_MIN, PagePlacement.Head, this);
}
}
/// <summary>
/// Gets the name of the embedded layout template.
/// </summary>
/// <remarks>
/// Override this property to change the embedded template to be used with the dialog
/// </remarks>
protected override string LayoutTemplateName
{
get { return null; }
}
#endregion
}
For this first post, we will be working with Kendo's PanelBar to display different Sitefinity content such as News items, blog posts, FAQ lists etc. Since this control has to consume different kind of contents from Sitefinity, it has to rely on the Content item type.
The KendoPanelBar is going to expose three different properties that look very similar to the DataBoundControl in ASP.NET
/// <summary>
/// Gets or sets the object from which the control retrieves a list of data items.
/// </summary>
/// <returns>
/// The object that contains the list of data that the control retrieves.
/// </returns>
public virtual object DataSource
{
get
{
return _dataSource;
}
set
{
if (value != null)
ValidateDataSource(value);
_dataSource = value;
}
}
/// <summary>
/// Gets or sets the name of the property for the item header.
/// </summary>
/// <returns>
/// The property name that is bound to the data item header.
/// </returns>
public string DataItemField { get; set; }
/// <summary>
/// Gets or sets the name of the property for the item content.
/// </summary>
/// <returns>
/// The property name that is bound to the data item content.
/// </returns>
public string DataContentField { get; set; }
Once we supply the control with a DataSource, it handles generating the HTML and the JavaScript code for us using:
private string BuildHtml()
{
if (DataSource == null)
{
throw new ArgumentException("DataSource is not supplied");
}
var builder = new StringBuilder();
builder.Append(String.Format("<ul id=\"{0}\" class=\"{1}\">", ControlId, CssClass));
var list = DataSource as IEnumerable<Content>;
if (list == null) return null;
foreach (var item in list)
{
builder.Append(string.Format("<li>{0}<div>{1}</div></li>", item.GetValue(DataItemField),
item.GetValue(DataContentField)));
}
builder.Append("</ul>");
return builder.ToString();
}
and
private string BuildScript()
{
var stringBuilder = new StringBuilder();
stringBuilder.Append("$(function() {");
stringBuilder.Append(string.Format("$('#{0}').kendoPanelBar(", ControlId));
stringBuilder.Append("{expandMode: 'single'});");
stringBuilder.Append("});");
return stringBuilder.ToString();
}
All we have to do on our pages is to add the Reference and tag:
<%@ Register TagPrefix="telerik" Namespace="SitefinityWebApp.Widgets.Kendo.Web" Assembly="SitefinityWebApp" %>
<telerik:KendoPanelBar ID="panelBar" runat="server">
</telerik:KendoPanelBar>
and now time for the fun part. Here is how we bind it with our Sitefinity content:
/// <summary>
/// Example showing how to bind list items to the KendoPanelBar control.
/// </summary>
private void BindData()
{
using(var manager = ListsManager.GetManager())
{
var listItems = manager.GetListItems().Where(i => i.Status == ContentLifecycleStatus.Live).OrderBy(i => i.Ordinal);
panelBar.DataContentField = "Content";
panelBar.DataItemField = "Title";
panelBar.DataSource = listItems;
panelBar.DataBind();
}
}
Et Voila, we have our Kendo server side control working. The output looks like the figure below:

P.S:
- This control is still work in progress so feel free to play around with the source code
- This control works with any kind of Sitefinity content of "Content" type
- The items could be templated but I would have to add some code for that.
- Your feedback / questions are appreciated.
- The ReadMe file is included for installation instructions.
Go ahead and download the source code from
here