Kamran
Kamran

Reputation: 4100

How to bind Repeater with list of objects GroupBy

First of all, Sorry for long detail. but its necessary to describe my problem. Every thing is self explainatory not so hard to read. Thanks!

I have list of Object from my class. List<CalendarEvent> allCalendarEvents = GetEvents();

public class CalendarEvent
{
    public int id { get; set; }
    public ID itemId { get; set; }
    public DateTime start { get; set; }
    public DateTime end { get; set; }
    public string subject { get; set; }
}

Now I wanted to group the events in the List allCalendarEvents by start date. So I used this code:

var monthList = from e in allCalendarEvents
                group e by e.start.Month into g
                orderby g.Key
                select new { month = g.Key, Event = g };

All the items in the list are now group by Month. So far so good. I used ASP Repeater to show the data to the user.

<asp:Repeater runat="server" ID="repMonths" OnItemDataBound="repMonths_OnItemDataBound">
    <ItemTemplate>
        <li>
            <%# Eval("month") %>

Code Behind

repMonths.DataSource = monthList;
repMonths.DataBind();

I can see the month number as output for my data, e.g. for the events in May, June,July, I see:

5
6
7

Now I want to show to the user how many CalenderEvents are inside one group of month. If I use use another repeater inside repMonths like this:

<asp:Repeater runat="server" ID="repMonths" OnItemDataBound="repMonths_OnItemDataBound">
    <ItemTemplate>
        <li>
            <%# Eval("month") %>
            <asp:Repeater runat="server" ID="repInnerEvent">
                <ItemTemplate>
                    <li>
                        <asp:Label runat="server" ID="lblEventName"></asp:Label>
                    </li>
                </ItemTemplate>
            </asp:Repeater>
        </li>
    </ItemTemplate>    
</asp:Repeater>

Then I don't know how to bind data with inner repeater. E.g.

protected void repMonths_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
    var item = e.Item.DataItem as ???; // I don't know what will come here
}

Upvotes: 1

Views: 2159

Answers (1)

j.f.
j.f.

Reputation: 3949

The first thing you'll need to do is actually find the inner repeater. You are on the right track. Use FindControl() on the repeater item to find it. Then once you have it, just simply assign the data source and bind it.

protected void repMonths_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
    // We only care if the repeater item is part of the <ItemTemplate>
    if(e.Item.ItemType == ListItemType.Item)
    {
        Repeater repInnerEvent = (Repeater)e.Item.FindControl("repInnerEvent");
        repInnerEvent.DataSource = // your data source
        repInnerEvent.DataBind();
    }
}

Sounds like the question isn't actually how to bind. It is how to get the data to bind. In that case, you already have your query written. You just need to know the month. In that case, I would use a label to hold the month.

<asp:Repeater runat="server" ID="repMonths" OnItemDataBound="repMonths_OnItemDataBound">
    <ItemTemplate>
        <li>
           <asp:Label ID="lblMonth" runat="server" Text='<%# Eval("month") %>'></asp:Label>
           <asp:Repeater runat="server" ID="repInnerEvent">
                <ItemTemplate>
                    <li>
                        <asp:Label runat="server" ID="lblEventName"></asp:Label>
                    </li>
                </ItemTemplate>
            </asp:Repeater>
        </li>
    </ItemTemplate>    
</asp:Repeater>

Then in the ItemDataBound, get that label and use its value.

protected void repMonths_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
    // We only care if the repeater item is part of the <ItemTemplate>
    if(e.Item.ItemType == ListItemType.Item)
    {
        // Get the month
        Label lblMonth = (Label)e.Item.FindControl("lblMonth");

        // Get the events for the month
        var eventList = from e in allCalendarEvents
                        where e.start.Month == lblMonth.Text
                        select e;

        // Bind your events to the inner repeater
        Repeater repInnerEvent = (Repeater)e.Item.FindControl("repInnerEvent");
        repInnerEvent.DataSource = eventList
        repInnerEvent.DataBind();
    }
}

Upvotes: 2

Related Questions