ASP.NET WebForms Nested Repeater With LINQ Group Data Source

2.7k views Asked by At

I have a LINQ grouping that I'd like to use to populate parent and child repeater controls.

<asp:Repeater ID="Parent" runat="server" OnItemDataBound="Parent_ItemDataBound">
    <ItemTemplate>
        <%# Eval("Key") %>
        <asp:Repeater ID="Child" runat="server">
            <ItemTemplate>
                <%# Eval("Id")  %>
                <%# Eval("Name")  %>
            </ItemTemplate>
        </asp:Repeater>
    </ItemTemplate>
</asp:Repeater>

public class Dog
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Breed { get; set; }
}

private IEnumerable<IGrouping<string, Dog>> GetDogs()
{
    var dogs = new List<Dog>
    {
        new Dog
        {
            Id = 1,
            Name = "Rex",
            Breed = "Poodle",
        },
        new Dog
        {
            Id = 2,
            Name = "Fido",
            Breed = "Terrier",
        },
        new Dog
        {
            Id = 3,
            Name = "Killer",
            Breed = "Pit Bull",
        }
    };

    return dogs.GroupBy(_ => _.Breed);
}

protected void Page_Load(object sender, EventArgs e)
{
    Parent.DataSource = GetDogs();
    Parent.DataBind();
}

protected void Parent_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    var item = e.Item;
    if ((item.ItemType == ListItemType.Item) || (item.ItemType == ListItemType.AlternatingItem))
    {
        var repeater = (Repeater)item.FindControl("Child");

        // I'm stuck on this code...
        //repeater.DataSource = what to do?
        //repeater.DataBind();
    }
}

I'm trying to set the child repeater's data source in the Parent_ItemDataBound event. How do I do this? item.DataItem is type object and I can't figure out how to obtain the list of dogs that's inside the data item.

2

There are 2 answers

0
cmd.prompt On BEST ANSWER

Expanding on Joshua's correct answer. If the 4.5 runtime is available to you, you can declare the types on the repeater itself so you will not have to bind the ItemDataBound event.

<ul>
    <asp:Repeater runat="server" ID="Parent" ItemType="IGrouping<String, Dog>">
        <ItemTemplate>
            <li><%# Item.Key %><ul>
            <asp:Repeater runat="server" ID="Child" ItemType="Dog" DataSource="<%#Item%>">
                <ItemTemplate>
                    <li><%# Item.Id %></li>
                    <li><%# Item.Name %></li>
                </ItemTemplate>
            </asp:Repeater>
            </ul></li>
        </ItemTemplate>
    </asp:Repeater>
</ul>
0
Joshua Leonard On

You can get the data from e.Item.DataItem. You should be able to cast this to IGrouping. Then you can get the inner repeater by looking for the control in the current repeaters repeateritem. Then bind the data from DataItem to the nested repeater.

This code below should work.

All this assumes you don't wrap the nested repeater in other controls.

    protected void Parent_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        var item = e.Item.DataItem as IGrouping<string, Dog>;
        if (item == null)
            return;

        if ((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem))
        {
            var repeater = e.Item.FindControl("Child") as Repeater;

            if (repeater != null)
            {
                repeater.DataSource = item;
                repeater.DataBind();
            }
        }
    }