Rendering n-column tables using the Repeater control

The ASP.NET Repeater control provides a template-based mechanism for rendering data using Data Binding. A basic usage sample can be found here .

The control uses the <ItemTemplate> tag for declaring HTML that should be rendered for each data item and a <SeparatorTemplate> tag to put some HTML between items. It also supports an <AlternatingItemTemplate> that can useful to render a fancy mixed two-color list or, more seriously, a two-column table. An example:

Page1.aspx

    <table border="1">
<asp:Repeater id="Repeater1" runat="server">
<ItemTemplate>
<tr>
<td>
<%# DataBinder.Eval(Container.DataItem, "ProductName") %>
</td>
</ItemTemplate>
<AlternatingItemTemplate>
<td>
<%# DataBinder.Eval(Container.DataItem, "ProductName") %>
</td>
</tr>
</AlternatingItemTemplate>
</asp:Repeater>
</table>

Page1.cs

        protected System.Web.UI.WebControls.Repeater Repeater1;

private void Page_Load(object sender, System.EventArgs e)
{
SqlConnection connection = new SqlConnection("Data Source=(local);Initial Catalog=Northwind;Integrated Security=SSPI;");
SqlCommand command = new SqlCommand("SELECT TOP 15 ProductId, ProductName FROM Products", connection);

            connection.Open();
Repeater1.DataSource = command.ExecuteReader(CommandBehavior.CloseConnection);
Repeater1.DataBind();
}

Resulting HTML

Alice Mutton

Aniseed Syrup

Boston Crab Meat

Camembert Pierrot

Carnarvon Tigers

Chai

Chang

Chartreuse verte

Chef Anton's Cajun Seasoning

Chef Anton's Gumbo Mix

Chocolade

Côte de Blaye

Escargots de Bourgogne

Filo Mix

Flotemysost

But what if need to render, lets say, a 3-column table?

Alice Mutton Aniseed Syrup Boston Crab Meat
Camembert Pierrot Carnarvon Tigers Chai
Chang Chartreuse verte Chef Anton's Cajun Seasoning
Chef Anton's Gumbo Mix Chocolade Côte de Blaye
Escargots de Bourgogne Filo Mix Flotemysost

And generically, a n-column table?

There's no <n-AlternatingItemTemplate> tag for this purpose. Yes, you could just programatically render the required HTML, loosing the design-time support. But you can also achieve this using a template-based approach maintaining design time support, using Data Binding events. Here's how.

 

A 3-column table using a template-based Repeater

To produce a 3-column table, all you need is render a <TD>...</TD> for each data item, and render a </TR><TR> every 3 items. Besides, you should place a <TR> befere the first item and a </TR> after the last item.

The difficult part on this is the "render a </TR><TR> every 3 items" thing. How can this be achieved using Data Binding? The answer is the ItemDataBound event.

When you invoke DataBind() method on a Data Binding enabled control, you can subscribe an event that is fired when each item is rendered. With some coding on this event, you can programmatically change the presentation of a specific data item. With this in mind, you can just count the items being rendered, and show or hide a separator </TR><TR> every three items.

A full example:

Page1.aspx

        <table border="1">
<tr>
<asp:Repeater id="Repeater1" runat="server">
<ItemTemplate>
<td><%# DataBinder.Eval(Container.DataItem, "ProductName") %></td>
</ItemTemplate>
<SeparatorTemplate>
</tr>
<tr>
</SeparatorTemplate>
</asp:Repeater>
</tr>
</table>

Page1.cs

        protected System.Web.UI.WebControls.Repeater Repeater1;
        protected int counter = 0;
protected int columnCount = 3;

private void Page_Load(object sender, System.EventArgs e)
{
SqlConnection connection = new SqlConnection("Data Source=(local);Initial Catalog=Northwind;Integrated Security=SSPI;");
SqlCommand command = new SqlCommand("SELECT TOP 15 ProductId, ProductName FROM Products", connection);

            connection.Open();
Repeater1.DataSource = command.ExecuteReader(CommandBehavior.CloseConnection);
Repeater1.ItemDataBound +=new RepeaterItemEventHandler(Repeater1_ItemDataBound);
Repeater1.DataBind();
}

        private void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Separator)
if((++counter % columnCount) != 0)
e.Item.Visible = false;
}

Cool? To get the full source code for this sample e-mail the author aribeiro@microsoft.com