Filtering content in Kentico

Standard repeaters are a great all-in-one web part for displaying content, but sometimes you need finer control over the output. This post will show you how to create a content filter for news articles, so that content can be filtered by the categories: Press Releases, Product News and Partner News.

How it works

Content will be filtered by dynamically changing the Where condition of the data source depending on the query string parameter of the URL. E.g. if the page URL is /News?Category=PressRelease, only articles tagged as a Press Release will be shown. Category buttons will be used to reload the page with a specific query string parameter.

Category selection

First of all, add a method for editors to tag content. Open the News Document type in Site Manager and go to the Fields tab. Add a new field with the following properties:

New field properties
Column name: Category
Attribute type: Text
Attribute size: 300
Allow empty value: Yes
Field caption: Category
Form control type: Input
Form control: Drop-down list
Data source: PressRelease; Press Release
ProductNews;Product News
PartnerNews;Partner News

You can now select one of these options from the Form tab when editing or creating a news article.

Design set up

In the Design tab of the news listing page, add three separate web parts: Documents Data Source, Filter and a Basic Repeater. Link them together using the following settings:

Documents data source settings
Web part control ID: DocumentsDataSource
Filter name: CategoryFilter
Path: /News%
Document types: CMS.News
Filter settings
Filter name: CategoryFilter
Filter control path: ~/Filters/CategoryFilter.ascx (we’ll create this file next)
Basic Repeater settings
Data source name: DocumentsDataSource (The ID of the data source control)
Transformation name: CorporateSite.Transformations.NewsList
(I’m building this in to the default Corporate site installation)

Writing the filter control

Create a new folder on the server called Filters and add a new ASP control file inside named CategoryFilter.ascx. Within this file create an unordered HTML list with a CSS selector of ‘buttonGroup’ containing three list elements. Add an ASP Link Button to each list element changing the ID’s and OnClick properties relative to the button. The code should look like this:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="CategoryFilter.ascx.cs" Inherits="CategoryFilter" %>
<ul class="buttonGroup">
  <li>
    <asp:LinkButton ID="PressReleaseButton" runat="server" EnableViewState="false" OnClick="PressReleaseButton_Click" Text="Press Releases" />
  </li>
  <li>
    <asp:LinkButton ID="ProductNewsButton" runat="server" EnableViewState="false" OnClick="ProductNewsButton_Click" Text="Product News" />
  </li>
  <li>
    <asp:LinkButton ID="PartnerNewsButton" runat="server" EnableViewState="false" OnClick="PartnerNewsButton_Click" Text="Partner News" />
  </li>
</ul>

The code behind file

Create a new code behind file for the above page, this must inherit the CMSAbstractBaseFilterControl. On page load, this will set the Where condition based on the URL query string parameter.

The code will also manage the click functions, which will simply reload the page with a different query string. (This doesn’t necessarily need to be set by the filter control, you could just add links in your page instead with different query strings.

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using CMS.GlobalHelper;
using CMS.CMSHelper;
using CMS.PortalControls;
using CMS.Controls;
public partial class CategoryFilter : CMSAbstractBaseFilterControl
{
  protected void Page_Load(object sender, EventArgs e)
  {
    string where = this.WhereCondition;
    string url = URLHelper.RawUrl;
    string urlParam = URLHelper.GetUrlParameter(url, "category");
    if (urlParam != "")
    {
      switch (urlParam)
      {
        case "PressRelease":
          where += " Category='PressRelease' ";
          break;
        case "ProductNews":
          where += " Category='ProductNews' ";
          break;
        case "PartnerNews":
          where += " Category='PartnerNews' ";
          break;
        default:
          where += "";
          break;
      }
    }
    if (where != "")
    {
      // Set where condition
      this.WhereCondition = where;
    }
    // Invoke changed event
    this.RaiseOnFilterChanged();
  }
  string Cat = "";
  protected void PressReleaseButton_Click(object sender, EventArgs e)
  {
    Cat = "PressRelease";
    redirectPage();
  }
  protected void ProductNewsButton_Click(object sender, EventArgs e)
  {
    Cat = "ProductNews";
    redirectPage();
  }
  protected void PartnerNewsButton_Click(object sender, EventArgs e)
  {
    Cat = "PartnerNews";
    redirectPage();
  }
  protected void redirectPage()
  {
    // Grab current URL
    string url = URLHelper.RawUrl;
    // Remove existing query parameters
    url = URLHelper.RemoveParameterFromUrl(url, "category");
    // Add new query parameters
    url = URLHelper.AddParameterToUrl(url, "category", Cat);
    // Redirect with new query parameters
    URLHelper.Redirect(url);
  }
}

Button styles

Add this CSS to create simple inline buttons that butt up against each other in a group:

.buttonGroup{
  margin: 0;
  padding: 0;
}
.buttonGroup li{
  border: 1px solid #CCCCCC;
  background: #F7F7F7;
  display: inline;
  list-style: none;
  margin: 0;
  padding: 4px 8px;
}
.buttonGroup li a{
  text-decoration: none;
  color: #66ADDF;
}

End result

Filter

All set! After setting a category for existing articles, clicking on a filter button will reload the page, adjusting the Where condition to display only the articles tagged with the category you selected.

Note: This is an adaptation of Kentico’s suggested custom filter in the Knowledge Base at devnet.kentico.com