Default text for empty Repeater control

Using VS 2008, I have a Repeater control:

<asp:Repeater runat="server" ID="storesRep" DataSourceID="storeSqlDataSource" 
    OnItemDataBound="StoresRep_ItemDataBound">
    <ItemTemplate>
        <table style="padding:0px">
        <tr>
            <td style="width:200px"><asp:Label ID="infoLbl" runat="server">
              Choose stores for upload:</asp:Label>&nbsp;&nbsp;&nbsp;&nbsp;
            </td>
            <td style="width:110px">
              <asp:Label ID="storeLbl" runat="server" Text='<%# Bind("Name") %>'>
              </asp:Label>&nbsp;&nbsp;
            </td>
            <td><asp:CheckBox runat="server" ID="storeCheck" /></td>
        </tr>
        </table>
    </ItemTemplate>
</asp:Repeater>
<asp:SqlDataSource ID="storeSqlDataSource" runat="server" 
    ConnectionString="<%$ ConnectionStrings:someConnectionString %>"
    SelectCommand="SELECT [StoreId], [Name] FROM [Store] Order By [Name]">
</asp:SqlDataSource>

Now I would like to display a default text like "No stores found" if data source returns no items from database. Until now I have mostly used GridView where I didn't have problems because of the EmptyDataText attribute.


Joaos answer can even be simplified. In the footer, do not set the visible-property of your default item to false, but use the following expression:

<FooterTemplate>
    <asp:Label ID="defaultItem" runat="server" 
        Visible='<%# YourRepeater.Items.Count == 0 %>' Text="No items found" />
</FooterTemplate>

This way, you can save the code behind.


Another possibility:

<FooterTemplate>
    <asp:Label ID="lblEmptyData" runat="server" Visible='<%# ((Repeater)Container.NamingContainer).Items.Count == 0 %>' Text="No items found" />
</FooterTemplate>

The benefit of this code snippet is that you aren't dependent on the ID you assigned to your repeater.


You could workaround the fact that Repeater does not support a inbuilt way to accomplish what you are doing by using the FooterTemplate in conjunction with the OnItemDataBound event and showing the footer only when the data source returns no items.

Examples on how you can do this can be found at:

Handling Empty Data in an ASP.NET Repeater control

How to show Empty Template in ASP.NET Repeater control?


Even better: this subclass adds an EmptyDataTemplate property. In your markup, put in an element just as you would an element. By default this will hide the header and footer if there's no data; you can change this with the HeaderVisibleWhenEmpty and FooterVisibleWhenEmpty properties in markup.

public class RepeaterWithEmptyDataTemplate : Repeater
{
    public virtual ITemplate EmptyDataTemplate { get; set; }

    protected virtual bool DefaultHeaderVisibleWhenEmpty
    {
        get { return false; }
    }

    protected virtual bool DefaultFooterVisibleWhenEmpty
    {
        get { return false; }
    }

    public bool HeaderVisibleWhenEmpty
    {
        get { return ViewState["hve"] == null ? DefaultHeaderVisibleWhenEmpty : (bool) ViewState["hve"]; }
        set { ViewState["hve"] = value; }
    }

    public bool FooterVisibleWhenEmpty
    {
        get { return ViewState["fve"] == null ? DefaultFooterVisibleWhenEmpty : (bool) ViewState["fve"]; }
        set { ViewState["fve"] = value; }
    }

    protected override void OnDataBinding(EventArgs e)
    {
        base.OnDataBinding(e);
        if (Items.Count == 0 && EmptyDataTemplate != null)
        {
            var emptyPlaceHolder = new PlaceHolder {ID = "empty", Visible = true};
            EmptyDataTemplate.InstantiateIn(emptyPlaceHolder);

            //figure out where to put placeholder
            RepeaterItem footer =
                Controls.OfType<RepeaterItem>().FirstOrDefault(i => i.ItemType == ListItemType.Footer);
            if (footer == null)
            {
                //add to end if no footer
                Controls.Add(emptyPlaceHolder);
            }
            else
            {
                Controls.AddAt(Controls.IndexOf(footer), emptyPlaceHolder);
            }

            //hide header and footer according to properties.
            foreach (RepeaterItem x in Controls.OfType<RepeaterItem>())
            {
                switch (x.ItemType)
                {
                    case ListItemType.Header:
                        x.Visible = HeaderVisibleWhenEmpty;
                        break;
                    case ListItemType.Footer:
                        x.Visible = FooterVisibleWhenEmpty;
                        break;
                }
            }
        }
    }
}

Sample in markup:

<myprefix:RepeaterWithEmptyDataTemplate runat=server>
    <ItemTemplate>blah blah blah</ItemTemplate>
    <EmptyDataTemplate>Hey, no data!</EmptyDataTemplate>
</myprefix:RepeaterWithEmptyDataTemplate>  

Please note that the DataBind method must be called, or the emptydatatemplate won't be displayed.