Nested Repeaters in ASP.NET
I've found that the simplest way to do nested repeaters without worrying about databinding events is to just set the DataSource using <%# %>
syntax.
For example:
<asp:Repeater runat="server" id="Departments"> <ItemTemplate> Name: <%# Eval("DeptName") %> Employees: <asp:Repeater runat="server" DataSource='<%# Eval("Employees") %>'> <ItemTemplate><%# Eval("Name") %></ItemTemplate> <SeparatorTemplate>,</SeparatorTemplate> </asp:Repeater> </ItemTemplate></asp:Repeater>
This is presuming that your Departments class has an Employees property - eg:
public class Department { public string DeptName {get; set;} public IEnumerable<Employee> Employees {get; set;}}public class Employee { public string Name {get; set;}}
If your outer-repeater object doesn't have a property corresponding to the inner-repeater object you can still use this trick, by adding a method in your code-behind that does the calculation. So your inner repeater might become:
<asp:Repeater runat="server" DataSource='<%# GetEmployees(Container.DataItem) %>'>
and then GetEmployees might look something like:
protected IEnumerable<Employee> GetEmployees(object item) { var dept = (Department) item; // then do whatever is necessary to get the employees from dept return employees;}
It's always cleaner to deal with the datasource than messing about with ItemDataBound, but this is even more the case when nesting Repeaters:
<asp:Repeater DataSource="<%#ColOfCol%>" runat="server"> <ItemTemplate> <tr> <asp:Repeater DataSource="<%#Container.DataItem%>" runat="server"> <ItemTemplate> <td><%#SomeExtractingMethodLikeEval()%></td> </ItemTemplate> </asp:Repeater> </tr> </ItemTemplate></asp:Repeater>
The inner datasource could also be an evaluated property, or a call to a method that returns the enumeration wanted. Just be aware that it will be called with an object. I prefer to write the specific version, and then overload:
protected IEnumerable<string> GetNames(Family fam){ foreach(Person p in fam.Members) yield return p.FirstName + " " + p.Surname;}protected IEnumerable<string> GetNames(object famObj){ return GetNames((Family)famObj);}
One thing to be aware of is that if you want to get the current object in the parent repeater than you have to obtain it with:
((RepeaterItem)Container.Parent.Parent).DataItem
You can nest repeaters without a problem. More then 2 levels deep gets nasty though. Here's how:
The html looks something like this:
<asp:Repeater ID="r1" runat="server" OnItemDataBound="r1_ItemDataBound"><ItemTemplate><!-- top level repeater element template here --> <asp:Repeater ID="r2" runat="server" onitemdatabound="r2_ItemDataBound"> <ItemTemplate><!-- child repeater element template here --> </ItemTemplate> </asp:Repeater></ItemTemplate></asp:Repeater>
The codebehind looks like this:
protected void r1_ItemDataBound(object sender, RepeaterItemEventArgs e) { Repeater r2 = (Repeater)e.Item.FindControl("r2"); r2.DataSource = yourDataSourceHere; // you'll have to query for appropriate data r2.DataBind(); } protected void r2_ItemDataBound(object sender, RepeaterItemEventArgs e) { // do the same thing here for the 3rd nested repeater if you have a third, and so on }