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.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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
        }
    }

Method 2

I don’t think there’s anything build into ASP.NET that allows this but you could do this:

<asp:Repeater ID="myRepeater" runat="server" OnItemDataBound="myRepeater_ItemDataBound">
    <ItemTemplate>
        <asp:PlaceHolder ID="twitterTemplate" Visible="false" runat="server">
             <asp:Literal ID="fooTwitterControl" runat="server" />
        </asp:PlaceHolder>

        <asp:PlaceHolder ID="itemTemplate" Visible="false" runat="server">
             <asp:Literal ID="fooItemControl" runat="server" />
        </asp:PlaceHolder>
    </ItemTemplate>
</asp:Repeater>

And the ItemDataBound event:

protected void myRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (ListItemType.Item == e.Item.ItemType || ListItemType.AlternatingItem == e.Item.ItemType)
    {
        PlaceHolder twitterTemplate = (PlaceHolder)e.Item.FindControl("twitterTemplate");
        PlaceHolder itemTemplate = (PlaceHolder)e.Item.FindControl("itemTemplate");

        var item = (LifestreamItem)e.Item.DataItem;
        if (item is LifestreamTwitterItem)
        {
            twitterTemplate.Visible = true;

            Literal fooTwitterControl = (Literal)e.Item.FindControl("fooTwitterControl");
            // Load all twitter related controls + populate
        }
        else
        {
            itemTemplate.Visible = true;
            Literal fooItemControl = (Literal)e.Item.FindControl("fooItemControl");
            // Load all non-twitter controls + populate
        }
    }
}

Essentially, the ItemTemplates become placeholders and enable/disable based on the type you’re iterating over.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x