Introduction
This article describes how to reap the benefits of the ASP.NET Repeater
control while at the same time be able to design your item templates in Visual Studio's WYSIWYG editors; instead of hand-writing the HTML.
Background
As with many other ASP.NET developers, I have found the benefits of the Repeater
control, and it's now one of my favorites. The only thing I didn't like about it was the fact that you had to manually edit the HTML to define the look of each item in the Repeater
. I would like to be able to graphically design the layout of my items in Visual Studio's WebForm designer. I would also like the ability to perform additional server-side logic for each item in the control to perform additional database look-ups, etc.
How It Works
The trick is to create a Web User Control and bind the data from the Repeater
's data source for each item as they are being bound. Visual Studio lets you visually design your Web User Control in its WYSIWYG editor. I won't go into the details of building Web User Controls here, but they're very simple.
In this example, the data source is a short list of CDs; each with a title, artist, and country (among other things). I generate this data source by reading a local XML file (I won't go into this process in this article, because it's very straight-forward). I want each CD's information to be displayed in single-record vertical format like this:
For added measure, I want to take advantage of the Repeater
's AlternatingItem
functionality and show every other CD with a yellow background, as shown above. (Ugly, yes, but it's just an example!)
The first thing I do is create a Web User Control called CDInfoControl
using Visual Studio's editors. In this control, I create the table layout, labels, and text fields for each property: Title, Artist, Country, etc. Please see the example project for details, but the generated HTML looks like this:
<%@ Control Language="vb" AutoEventWireup="false"
Codebehind="CDInfoControl.ascx.vb"
Inherits="WebApplication4.CDInfoControl" %>
<asp:Panel id="pnlMain" runat="server">
<TABLE id="Table5"
style="FONT-SIZE: x-small; FONT-FAMILY: Tahoma" borderColor="#000000"
cellSpacing="0" cellPadding="1" border="1">
<TR>
<TD bgColor="lightblue"><STRONG>
<FONT style="BACKGROUND-COLOR: lightblue">Title:</FONT></STRONG>
</TD>
<TD><asp:Label id="lblTitle" runat="server"></asp:Label></TD>
</TR>
<TR>
<TD bgColor="lightblue"><STRONG>
<FONT style="BACKGROUND-COLOR: lightblue">Artist:</FONT></STRONG><
/TD>
<TD><asp:Label id="lblArtist"
runat="server"></asp:Label></TD>
</TR>
<TR>
<TD bgColor="#add8e6"><STRONG>Country:</STRONG>
</TD>
<TD><asp:Label id="lblCountry" runat="server"></asp:Label></TD>
</TR>
<TR>
<TD bgColor="#add8e6">
<STRONG>Currency:</STRONG></TD>
<TD><asp:Label id="lblCurrency"
runat="server"></asp:Label></TD>
</TR>
</TABLE>
</asp:Panel>
The design-view looks like this:
Next, I edit the main page's HTML to include my user control inside the Repeater
. This is the only time I need to manually edit the HTML for the Repeater
. The result looks like this:
<asp:repeater id="Repeater1" runat="server">
<HeaderTemplate>
<table width="100%" style="font: 8pt verdana" ID="Table5">
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<uc1:CDInfoControl id="CDInfo" runat="server"></uc1:CDInfoControl>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:repeater>
Notice that I created an instance of CDInfoControl
named CDInfo
and placed it inside the Repeater
. I also had to do the .NET wire-up to define the control, as you can see in the sample application. I cheated a little by dragging the control onto my form and then editing the HTML source to move the control to inside of my Repeater
. This way, Visual Studio took care of the wire-ups for me!
The next step is to handle the Repeater
's ItemDataBound
event to send the data to my control. ASP.NET creates a new instance of my control for each record in the data source, so I simply cast the argument as a DataRowView
and call a Public Sub
(explained next) of my control.
Private Sub Repeater1_ItemDataBound(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) _
Handles Repeater1.ItemDataBound
If (e.Item.ItemType = ListItemType.Item) Then
CType(e.Item.FindControl("CDInfo"), _
CDInfoControl).SetData(CType(e.Item.DataItem, _
DataRowView), False)
End If
If (e.Item.ItemType = ListItemType.AlternatingItem) Then
CType(e.Item.FindControl("CDInfo"), _
CDInfoControl).SetData(CType(e.Item.DataItem, _
DataRowView), True)
End If
End Sub
Finally, I need to handle this data binding in my control, so I create a Public Sub
named SetData
, which accepts the DataRowView
and a flag indicating whether or not this is an AlternatingItem
. All I do in this Sub
is to populate the labels and fields of my control.
Public Sub SetData(ByVal dr As DataRowView, _
ByVal IsAlternating As Boolean)
Me.lblTitle.Text = dr("title")
Me.lblArtist.Text = dr("artist")
Me.lblCountry.Text = dr("country")
Me.lblCurrency.Text = GetCurrency(dr("country"))
If IsAlternating Then
pnlMain.BackColor = Color.LightGoldenrodYellow
End If
End Sub
Notice that I don't have to depend only on the data from the Repeater
. In this example, I get the currency from a private function within my control. This could trigger a database lookup, additional logic, etc. This really makes the Repeater
control powerful.
Points of Interest
I didn't go into every detail of the sample, but it's very easy to follow. The point I wanted to get across was the use of a Web User Control in concert with a Repeater
to give you the most benefit.