Search code examples
c#asp.netrazor

ASP Repeater control with multiple templates


How can I have a repeater control with multiple templates where the template chosen is based upon the type of the item?

This is what I have currently:

My repeater class:

[ToolboxData("<{0}:LifestreamRepeater runat=server>")]
public class LifestreamRepeater : Repeater
{

    [PersistenceMode(PersistenceMode.InnerProperty)]
    public ITemplate TwitterTemplate {get; set;}


    protected override void OnDataBinding(EventArgs e)
    {
        //base.OnDataBinding(e);
        foreach (var item in (IEnumerable<LifestreamItem>)this.DataSource)
        {
            if (item is LifestreamTwitterItem)
            {
                LifestreamRepeaterItem ri = new LifestreamRepeaterItem(item);
                TwitterTemplate.InstantiateIn(item);
            }
            else
            {
                ItemTemplate.InstantiateIn(item);
            }
        }

    }
}

and the front end:

        <lfs:LifestreamRepeater runat="server" ID="repeater1">
            <TwitterTemplate>
                <div class="Lifestream Twitter Item">
                    <h4> <%# DataBinder.Eval(Container.DataItem, "Title")%> </h4>
                    <p>  <%# DataBinder.Eval(Container.DataItem, "Body")%> </p>
                </div>
            </TwitterTemplate>
            <ItemTemplate>
                <div class="Lifestream Item">
                    <h2> <%# DataBinder.Eval(Container.DataItem, "Title")%> </h2>
                    <p>  <%# DataBinder.Eval(Container.DataItem, "Body")%> </p>
                </div>
            </ItemTemplate>
        </lfs:LifestreamRepeater>

Then I bind the repeater control to an IEnumerable of LifestreamItem which is a base class for multiple different social network post types so there might be TwitterLifestreamItem and VimeoLifestreamItem and I want the repeater to choose a different template, with different possible values, depending on the dataitem.


Solution

  • It seems that the solution is to override the DataBind method like this:

        public override void DataBind()
        {
            foreach (var item in (IEnumerable<LifestreamItem>)this.DataSource)
            {
                if (item is LifestreamTwitterItem)
                {
                    TwitterTemplate.InstantiateIn(item); // instantiate inside the item which is also a control.
                }
                else
                {
                    ItemTemplate.InstantiateIn(item);
                }
                item.DataBind(); // bind the item
                Controls.Add(item); // add the item to the repeater
            }
        }