One of the requirements I had when designing skins for SubText was the ability to select which links will be displayed on the sidebar. This is especially handy for changing the content based on the page the visitor is on. I did some digging into the codebase for SubText and found a very neat way of adding the support to the SingleColumn control. The following article will describe the process to make this modification to SubText. For purposes of this article I used the SubText 2.1.0.5 source code. The latest source code for SubText can be downloaded via Subversion at Google Code. The update will only affect the SubText.Web assembly and all the source files referred to is in the associated SubText.Web project.

Step 1: Add Selection Property to SingleColumn.cs

First add a new property to the SingleColumn.cs code file in UI\Controls. This will become the property selector we will use when adding the control to the skin file later. The property we are adding is of the CategoryList type already defined inside SubText. We use the CategoryList.None option to display all the original list, and this is the default value for the UseCategory variable. This ensures the control will still work with existing skins as it used to.  The following code creates the required property:

   1: private CategoryType UseCategory = CategoryType.None;
   2:  
   3: public CategoryType DisplayCategory
   4: {
   5:     get { return UseCategory; }
   6:     set { UseCategory = value; }
   7: }

Step 2: Modify the GetArchiveCategories() method

The GetArchiveCategories() method needs to be modified to check which category item has been selected. In this implementation I am using if() statements to do the check but it can be changed to use a switch() statement if required. The change to the method is shown below, and implemented to ensure support for existing skins.

   1: protected IList<LinkCategory> GetArchiveCategories()
   2: {
   3:     List<LinkCategory> lcc = new List<LinkCategory>();
   4:  
   5:     if (UseCategory == CategoryType.StoryCollection || UseCategory == CategoryType.None)
   6:     {
   7:         LinkCategory storyCollection = UIData.Links(CategoryType.StoryCollection, CurrentBlog.UrlFormats);
   8:         if (storyCollection != null)
   9:             lcc.Add(storyCollection);
  10:     }
  11:  
  12:     if (UseCategory == CategoryType.ArchiveMonthCollection || UseCategory == CategoryType.None)
  13:     {
  14:         LinkCategory archiveMonth = UIData.ArchiveMonth(CurrentBlog.UrlFormats);
  15:         if (archiveMonth != null)
  16:             lcc.Add(archiveMonth);
  17:     }
  18:  
  19:     /*   
  20:      * Uncomment this to test the Category Archive with post count
  21:      * and comment to following block of code 
  22:      */ 
  23:  
  24:     //LinkCategory archiveCategories = UIData.ArchiveCategory(CurrentBlog.UrlFormats);
  25:     //if (archiveCategories != null)
  26:     //    lcc.Add(archiveCategories);
  27:  
  28:  
  29:     if (UseCategory == CategoryType.PostCollection || UseCategory == CategoryType.None)
  30:     {
  31:         LinkCategory postCollection = UIData.Links(CategoryType.PostCollection, CurrentBlog.UrlFormats);
  32:         if (postCollection != null)
  33:             lcc.Add(postCollection);
  34:     }
  35:  
  36:     if (UseCategory == CategoryType.ImageCollection || UseCategory == CategoryType.None)
  37:     {
  38:         LinkCategory imageCollection = UIData.Links(CategoryType.ImageCollection, CurrentBlog.UrlFormats);
  39:         if (imageCollection != null)
  40:             lcc.Add(imageCollection);
  41:     }
  42:  
  43:     if (UseCategory == CategoryType.LinkCollection || UseCategory == CategoryType.None)
  44:     {
  45:         lcc.AddRange(Links.GetActiveCategories());
  46:     }
  47:     return lcc;
  48: }

Step 3: Change the inheritance to BaseControl

Because the SingleColumn inherits from the CachedColumnControl we need to change this to BaseControl. The problem with the CachedColumnControl is that it will not always detect the changes to the DisplayCategory property. The change is shown below.

   1: public class SingleColumn : BaseControl

Once we have completed these steps recompile the project to ensure that there is no errors before continuing. To implement the updated control is fairly simple. Create a new control that inherits from the new SingleColumn control and add a CategoryList control to it. Then reference the new SingleColumn control in the control you want to display the content.

Step 4: Create new SingleColumn Control

Create a new WebUserControl which inherits from SingleColumn and contains a CategoryList control. In this case the new control is called SingleColumnItem.ascx and contains the following code.

   1: <%@ import namespace="Subtext.Framework" %>
   2: <%@ control language="C#" enabletheming="false" inherits="Subtext.Web.UI.Controls.SingleColumn" %>
   3: <%@ register tagprefix="uc1" tagname="CategoryList" src="CategoryList.ascx" %>
   4: <uc1:categorylist id="Categories" runat="server" />

Step 5: Add the new control to HomePage.ascx and specify the content to load

Add the new control to any control, in this case HomePage.ascx and specify the content to load as follows:

   1: <%@ register tagprefix="uc1" tagname="SingleSideItem" src="SingleSideItem.ascx" %>
   2: <uc1:singlesideitem id="ucArticles" runat="server" displaycategory="StoryCollection" />
   3: <uc1:singlesideitem id="ucImages" runat="server" displaycategory="ImageCollection" />
   4: <uc1:singlesideitem id="ucPostCategories" runat="server" displaycategory="PostCollection" />

This simple change makes it possible to break the SingleColumn control in to multiple pieces that changes depending on where or how it is loaded.