Ever questioned the implementation of the Repeater control? Yes we've all had requirements where this control comes in handy. The thing that detracted me and many developers I've spoken with is the use of DataBinder.Eval in the front end code. There are online examples that attempt to explain everything that needs to happen to move the binding logic to the compiled code, but once more, I learned that I had to figure out the details on my own. Next time you need the repeater functionality, stop struggling with HTML in the code to generate your output, and wincing at DataBinder.Eval in the front end code. When you understand these method's you'll be satisfied with the repeater at last.
<%@ control language="c#" autoeventwireup="false" codebehind="NestedRepeater.ascx.cs"
inherits="YourProject.UserControls.NestedRepeater" targetschema="http://schemas.microsoft.com/intellisense/ie5" %>
<%@ import namespace="System.Data" %>
<asp:Repeater ID="AreaResults" OnItemDataBound="AreaResults_ItemDataBound" runat="server">
<HeaderTemplate>
<table border="0" cellpadding="0" cellspacing="0">
</HeaderTemplate>
<ItemTemplate>
<tr>
<td valign="top">
<a href="?AreaID=<%# ((DataRowView)Container.DataItem)[" AreaID?]%>?">
<img border="0" src="<%# ((DataRowView)Container.DataItem)["ImageLink"]%>" hspace="3px"
vspace="3px" alt="View Area Detail">
</a>
</td>
<td>
<a href="?AreaID=<%# ((DataRowView)Container.DataItem)[" AreaID?]%>?">
<%# ((DataRowView)Container.DataItem)["AreaName"]%></a> -
<%# ((DataRowView)Container.DataItem)["AreaDescription"]%>
<asp:Repeater ID="PropertyResults" runat="server">
<HeaderTemplate>
<table border="0" cellpadding="0" cellspacing="0">
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<a href='?PropertyID=<%# ((DataRowView)
Container.DataItem)["PropertyID"]%>'>
<%# ((DataRowView)Container.DataItem)["PropertyName"]%>
</a>
</td>
<td width="10">
</td>
<td>
<%# ((DataRowView)Container.DataItem)["DistanceToCentroid"]%>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
<tr>
<td colspan="3" height="10">
</td>
</tr>
</table>
</FooterTemplate>
</asp:Repeater>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
Server Code
I have given you one generic method that handles your data and binding, only to illustrate the necessary steps. I'm quite sure, you are a master of your data at this point so I've excluded impertinent details about data retrieval and manipulation. Pay special attention to the comments.
protected void massageData()
{
DataSet resultSet = new DataSet("resultSet");
DataTable AreaDT = new DataTable("AreaDT");
DataTable PropertyDT = new DataTable("PropertyDT");
/* * Populate your data tables with your chosen method * */
//Add DataTables to DataSet and create the one-to-many
//relationships (as many as you need)
resultSet.Tables.Add(AreaDT);
resultSet.Tables.Add(PropertyDT);
resultSet.Relations.Add("PropertiesInArea",
AreaDT.Columns["AreaID"],PropertyDT.Columns["AreaID"]);
/* Important!!! Only set the data source for the
* topmost parent in the heirarchy.
* The nested repeaters that are buried in the topmost
* parent will not be in scope until binding
* when using this server-style binding method. */
AreaResults.DataSource = resultSet.Tables["AreaDT"];
//Upon databind, you invoke the ItemDataBound Method,
//which can be easily created by the events tab
//under the properties of the repeater control in the designer
AreaResults.DataBind();
AreaResults.Visible = true;
}
protected void AreaResults_ItemDataBound(object sender, System.Web.UI.WebControls.RepeaterItemEventArgs e)
{
//Only consume the items in the parent repeater
//pertinent to nesting
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
//Now that the nested repeater is in scope, find it,
//cast it, and create a child view from
//the datarelation name, and specify that view as the
//datasource. Then bind the nested repeater!
Repeater tempRpt =
(Repeater)e.Item.FindControl("PropertyResults");
if (tempRpt != null)
{
tempRpt.DataSource =
((DataRowView)e.Item.DataItem).CreateChildView("PropertiesInArea");
tempRpt.DataBind();
}
}