ASP.NET

How to bind an ASP.NET Repeater control (C#)

ASP.NET · · Published 2026-09-04

The Repeater is the simplest data-bound control in Web Forms: it renders a template once per item and adds nothing of its own. No table, no styles, no paging. That makes it ideal for lists, cards and any markup the GridView cannot produce.

Markup

<asp:Repeater ID="rptArticles" runat="server" ItemType="Demo.ArticleSummary"
    OnItemDataBound="rptArticles_ItemDataBound" OnItemCommand="rptArticles_ItemCommand">
    <HeaderTemplate><ul class="articles"></HeaderTemplate>
    <ItemTemplate>
        <li>
            <a href='<%# "Article.aspx?id=" + Item.Id %>'><%#: Item.Title %></a>
            <time datetime='<%# Item.Published.ToString("yyyy-MM-dd") %>'><%# Item.Published.ToString("d MMM yyyy") %></time>
            <asp:Label ID="lblNew" runat="server" CssClass="badge" Text="New" Visible="false" />
            <asp:LinkButton runat="server" CommandName="Archive" CommandArgument='<%# Item.Id %>' Text="Archive" />
        </li>
    </ItemTemplate>
    <FooterTemplate></ul></FooterTemplate>
</asp:Repeater>
<asp:PlaceHolder ID="phEmpty" runat="server" Visible="false"><p>No articles yet.</p></asp:PlaceHolder>

Templates: HeaderTemplate and FooterTemplate render once, ItemTemplate per item, AlternatingItemTemplate (optional) for every second item, SeparatorTemplate between items. Note that the opening <ul> in the header and the closing tag in the footer form one element in the output.

ItemType (.NET 4.5 and later) gives strongly typed access through Item, checked at compile time. Without it, use Eval("Title"), which resolves the property by name at run time.

Code-behind

public class ArticleSummary
{
    public int Id { get; set; }
    public string Title { get; set; }
    public DateTime Published { get; set; }
}

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack) Bind();
}

private void Bind()
{
    var list = new List<ArticleSummary>();
    using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["Db"].ConnectionString))
    using (var cmd = new SqlCommand(
        "SELECT TOP (20) ArticleId, Title, PublishedOn FROM dbo.Articles WHERE Archived = 0 ORDER BY PublishedOn DESC", con))
    {
        con.Open();
        using (var r = cmd.ExecuteReader())
            while (r.Read())
                list.Add(new ArticleSummary { Id = r.GetInt32(0), Title = r.GetString(1), Published = r.GetDateTime(2) });
    }
    rptArticles.DataSource = list;
    rptArticles.DataBind();
    phEmpty.Visible = list.Count == 0;
}

protected void rptArticles_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType != ListItemType.AlternatingItem) return;
    var a = (ArticleSummary)e.Item.DataItem;
    e.Item.FindControl("lblNew").Visible = a.Published > DateTime.Today.AddDays(-7);
}

protected void rptArticles_ItemCommand(object source, RepeaterCommandEventArgs e)
{
    if (e.CommandName == "Archive" && int.TryParse((string)e.CommandArgument, out int id))
    {
        ArticleRepository.Archive(id);
        Bind();
    }
}

Paging is not built in; see Paging a Repeater. For a table with editing and sorting, the GridView is the better fit: Bind a GridView.

Official documentation