Banner

Widget Template Code Customized the Easy Way

Nov 5, 2017
Sitefinity's Widget Templates provide a quick and easy way to change how Sitefinity renders widgets, both for built-in content types as well as custom ones. In the backend, it's just a hop, skip, and a jump away to Design > Widget Templates to access a majority of the templates where you can manipulate the HTML used to render them. Oftentimes, though, you have to do more. Let's say that, when iterating over a list of news items in the "Titles only" template you want to add a CSS class to some of the items, but not others. This goes beyond what the News widget itself is capable of (which can filter news items from being displayed entirely based on your selected List settings) and needs to be done in the widget template itself. So how can this be done? There's more to this than simple markup, as the CSS class has to be applied conditionally. You could do it via JavaScript, but that has to wait for the widget to finish rendering before retroactively applying changes, and if poorly done could cause a "flicker", where the end user sees the pre-altered items for a moment before the JavaScript gets a chance to run. You could ditch the out-of-the-box widget template and create your own ASCX file in your project, to then expose a code-behind. But in an ideal world, we wouldn't have to make that extra step and we wouldn't have to not use the widget template provided by Sitefinity out-of-the-box. Thankfully, the ideal world is the one we live in! With just a few simple edits to the existing widget template you can expose any arbitrary UserControl code-behind to the widget template, which gives you very powerful customization access to Sitefinity widget templates. Let's see how it's done.

Create Your Code File

In your Sitefinity solution, find a suitable location for your custom code-behind file and create it there. It can exist anywhere: In the Sitefinity project, an external code library, a DLL reference, anywhere at all! As long as your Sitefinity web application can reference it, it's fair game. For simplicity I am creating mine right within SitefinityWebApp, inside a "Custom" directory.
01CustomCode
 I'll save and build the project, and start up my Sitefinity site. We'll get back to the code in a moment. But first, let's make the necessary modification to the widget template we plan on overriding.

Modifying the Widget Template

As stated before, head to the backend, then go to Design > Widget Templates. In this example, I'm going to be customizing the "Titles only" News widget template. Search for it and click its title to open up the edit screen. At the very top of the widget template, we need to add an "Inherits" property to the declaration at the top. This is the glue that will stick the widget template to our custom code. Set the "Inherits" property to the namespace and name of our class.

<%@ Control Language="C#" Inherits="SitefinityWebApp.Custom.CustomCodeBehind" %>

Click "Save changes" and you're done! Now the "Titles only" widget template is hooked up to our custom code behind file. But until we configure our code-behind properly, we're not accomplishing much.

Customizing Widget Template via Code Behind

Back in our code, the first thing we must do in order for it to work with widget template at all is to make it inherit from "UserControl" (the standard one from the System.Web.UI namespace). This will allow the widget template to render properly and give us access to very useful methods that we can utilize to access information from the widget template.
02Namesapce
Now we can get to the meat and potatoes. Let's say we want to change a few of the hyperlinks, where every even item in the list gets **bold**. Here's what a page with the "Titles only" template currently looks like, after saving and building our project so that our code-behind now works correctly (though doesn't currently change anything):
03templatebefore
Our code behind is in place and officially not interfering with the rendering. Let's add our rather simple feature now. The first thing we need to do is obtain a reference to the RadListView that the widget uses to render the news items. The ID of this view is "NewsList" (which can be found, and changed if desired, in the widget template itself). Generally-speaking, you have access to any control or HTML element within the widget template that has runat="server" on it (much like a typical ASP.NET code-behind). If you require access to an element and it lacks either of those properties, you can add them yourself to expose them. In our example, we don't need to, however, so we can move along without making further widget template edits. We don't need the RadListView specifically, but rather its bound news items. As such, we want to hook up a method to its ItemDataBound event. We'll do so by overriding "OnInit", using "FindControl" to obtain our RadListView, then hook a custom method up to said event within the OnInit method.

using System;
using System.Web.UI;
using Telerik.Web.UI;
  
namespace SitefinityWebApp.Custom
{
    public class CustomCodeBehind : UserControl
    {
        protected override void OnInit(EventArgs e)
        {
            RadListView newsList = FindControl("NewsList") as RadListView;
            if (newsList == null)
            {
                return;
            }
            newsList.ItemDataBound += AddBold;
        }
  
        private static void AddBold(object sender, RadListViewItemEventArgs eventArgs)
        {
            throw new NotImplementedException();
        }
    }
}


Now we have access to each of the RadListView's items as it is created. We have to do a little work to get to the real data item, though, since the passed-in event arguments is not of the right type initially. Once we do that, though, we can check to see if the item is an even one (using modulo), find the "DetailsViewHyperLink" defined in the widget template that creates the anchor on the page, and alter its style to make it bold. The completed example is listed here:

using System;
using System.Web.UI;
using Telerik.Web.UI;
 
namespace SitefinityWebApp.Custom
{
    public class CustomCodeBehind : UserControl
    {
        protected override void OnInit(EventArgs e)
        {
            RadListView newsList = FindControl("NewsList") as RadListView;
            if (newsList == null)
            {
                return;
            }
            newsList.ItemDataBound += AddBold;
        }
 
        private static void AddBold(object sender, RadListViewItemEventArgs eventArgs)
        {
            throw new NotImplementedException();
        }
    }
}


In this example, we don't need access to the literal NewsItem at all. But if we did, all you'd have to do is add "using Telerik.Sitefinity.News.Model;" to the top of the file, and once you have "radListViewItem" as a RadListViewDataItem, you can access the news item via the DataItem property:

NewsItem newsItem = radListViewItem.DataItem as NewsItem;
if (newsItem == null)
{
    return;
}
 
// Access newsItem properties here.


But in our case, we only care about the rows themselves. In the complete code example above, we're getting the RadListViewDataItem, checking its DisplayIndex property so that we make sure to only modify even rows, then proceed to do so by fetching the "DetailsViewHyperLink" property and adding a "style" to the final output. In a more realistic scenario you wouldn't add an inline style of course: You'd likely add a CSS class called "alternate" or something to that effect, so that the presentation is correctly kept in a CSS file instead of being burrowed in a code-behind and hardcoded. For example purposes, however, this serves us well enough. Indeed, here is the result:

04templateafter

Mission Complete

That's it! We were able to dig into the guts of a widget template's properties and make modifications without having to resort to completely ditching built-in Sitefinity widget templates and creating our own from scratch. Since we expose C# to the widget template, the capabilities of widget templates expand a great deal, as any amount of logic you can code you can now apply to them. You are no longer hampered by having to either kludge logic in via JavaScript or via clunky "code-front" like syntax, and can even share common functionality between widget templates by calling common C# classes you create!
Load more comments
comment-avatar

Copyright © 2017 Alain "Lino" Tadros