.aspx files avoiding code-behind files because in my opinion it increases readability and manageability. One of the main drawbacks when using the Repeater in conjunction with databinding syntax is the need for casting the
DataItem property to it's actual type:I would like to share my take on a strongly typed Repeater which removes the need for casting objects, increases productivity and readability and unlocks intellisense!
The solution
The solution requires you to create two base classes which includes the core functionality and then for every typed Repeater create a simple inherited class which defines the type. As you might have noticed in the above screenshot I introduced a new property called
TypedItem. You are free to create a name which suits your needs e.g. Container.I for improved readability.Setting up the base classes:
1. Create a generic Repeater base class
This is the main workhorse of the solution. It was neccessary to override the
InitializeItem method of the Repeater class because the default Repeater works with the private variables for the templates. This implementation uses the properties for each template which is required because we will be overriding the ItemTemplate and AlternatingItemTemplate for our typed Repeaters.Also the
CreateItem method is overriden to actually create a generic RepeaterItem<T> which will be created in step 2.using System.Web.UI;
using System.Web.UI.WebControls;
public class GenericRepeaterBase<T> : Repeater where T : class
{
protected override RepeaterItem CreateItem(int itemIndex, ListItemType itemType)
{
return CreateRepeaterItem(itemIndex, itemType);
}
private static GenericRepeaterItem<T> CreateRepeaterItem(int itemIndex, ListItemType itemType)
{
return new GenericRepeaterItem<T>(itemIndex, itemType);
}
protected override void InitializeItem(RepeaterItem item)
{
ITemplate template = (ITemplate)null;
switch (item.ItemType)
{
case ListItemType.Header:
template = HeaderTemplate;
break;
case ListItemType.Footer:
template = FooterTemplate;
break;
case ListItemType.Item:
template = ItemTemplate;
break;
case ListItemType.AlternatingItem:
template = AlternatingItemTemplate;
if (template != null)
break;
else
goto case 2;
case ListItemType.Separator:
template = SeparatorTemplate;
break;
}
if (template == null)
return;
template.InstantiateIn((Control)item);
}
}
2. Create a generic RepeaterItem base class
This class contains the property that you use while working with the Repeater. You can rename the
TypedItem property as you wish.using System.Web.UI.WebControls;
public class GenericRepeaterItem<T> : RepeaterItem where T : class
{
public GenericRepeaterItem(int itemIndex, ListItemType itemType)
: base(itemIndex, itemType)
{
}
public T TypedItem
{
get { return (T)this.DataItem; }
}
}
Usage:
3. Create a typed Repeater
Now for every Repeater that you would like to use strongly typed you must create an easy implementation of the
GenericRepeaterBase<T> class. The example below creates the PersonRepeater mentioned before.The
PersistenceMode attribute needs to be redefined because it is not automatically inherited. The TemplateContainer attribute and the generic type definition on the class make the neccessary definitions for the Repeater to work.public class PersonRepeater : GenericRepeaterBase<GenericRepeaterItem<Person>>
{
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(GenericRepeaterItem<Person>))]
public override ITemplate ItemTemplate { get; set; }
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(GenericRepeaterItem<Person>))]
public override ITemplate AlternatingItemTemplate { get; set; }
}
4. Use it!
public class Person
{
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
<%@ Register TagPrefix="asp" Namespace="TypedRepeater" Assembly="TypedRepeater" %>
<asp:PersonRepeater runat="server">
<ItemTemplate>
Name: <% #Container.TypedItem.Name %><br />
Date of birth: <%#Container.TypedItem.DateOfBirth.ToShortDateString() %>
</ItemTemplate>
</asp:PersonRepeater>
I hope this code brings you lots of joy! ;)

