55

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.

João Angelo
  • 56,552
  • 12
  • 145
  • 147
AGuyCalledGerald
  • 7,882
  • 17
  • 73
  • 120

8 Answers8

82

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.

AGuyCalledGerald
  • 7,882
  • 17
  • 73
  • 120
31

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.

brz
  • 1,846
  • 21
  • 21
27

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?

João Angelo
  • 56,552
  • 12
  • 145
  • 147
  • @marquito If you feel sad about the semantic dissonance, you could always use a `Panel` and show/hide that in `OnItemDataBound` instead of the FooterTemplate... – pseudocoder Nov 21 '13 at 15:21
  • @pseudocoder the sadness comes from the lack of an out-of-the-box way to do it. Furthermore, I'm forced to check on every databound item just to check if the final result is empty. There should also be a "OnFinishedDataBinding" event which would prevent unnecessary calls to OnItemDataBound. – marquito Nov 22 '13 at 11:03
  • I was able to use this approach successfully after several tries with different methods. I do think that using `panel` in place of `label` would add even more flexibility, and I look forward to trying that as well. Thanks for sharing this! – Dylan Kinnett Jan 19 '16 at 15:36
  • I'm gonna hope you know better by now but link only answers kinda suck... – Ortund Mar 05 '19 at 16:40
  • @Ortund you need to be less radical; the answer contains two external links **for examples**. The answer is use the `FooterTemplate` and additional logic... In conclusion, what I know better by now is that the Internet (SO included) should be more friendly! – João Angelo Mar 19 '19 at 12:06
  • @JoãoAngelo and what happens when those links die? Then your answer is of no use to anybody. That's why [how to answer](https://stackoverflow.com/help/how-to-answer) specifically says that you should provide context for the most important parts of the link that you're sharing. This isn't me being an asshole; this is accepted practice on this site. – Ortund Mar 24 '19 at 14:14
  • 1
    @Ortund this isn't a link-only answer. It does cover the basic idea and links to examples, which is fine. However, it isn't a specifically *good* answer, but it's far from delete worthy. If you feel like it, downvote the answer, and please read https://meta.stackexchange.com/q/225370/332043 – Zoe Mar 24 '19 at 14:22
  • @Zoe k... I mean I'm sure I also earned my requisite 3k reputation to help with question/answer review, triage, etc. but hell... what do I know anyway right? I would have flagged this as link only. Examples from dead links still don't help anybody. – Ortund Mar 25 '19 at 07:35
7

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.

Xavier J
  • 4,326
  • 1
  • 14
  • 25
1

You can use a footer template to manage massage, like this

Step 1

<FooterTemplate>
    <%-- Label used for showing Error Message --%>
    <asp:Label ID="lblDefaultMessage" runat="server" Text="Sorry, no item is there to show." Visible="false">
    </asp:Label>
</FooterTemplate> 

Step 2

Handle visibility of lable in Repeater_ItemDataBound event like

protected void Repeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
 if (Repeater.Items.Count < 1)
  {
    if (e.Item.ItemType == ListItemType.Footer)
    {
        Label lblDefaultMessage= (Label)e.Item.FindControl("lblDefaultMessage");
        lblDefaultMessage.Visible = true;
    }
  }
}
Nitin Singh
  • 160
  • 1
  • 8
0

On the basis of answer n. 3 i adopted the following solution which seems good enough to me:

<asp:Literal ID="emptyDataRowCnt" runat="server" Visible='<%# MyRepeater.Items.Count == 0 %>'>
    <li class="row emptyDataRow">No data here</li>
</asp:Literal>
Zoe
  • 27,060
  • 21
  • 118
  • 148
erionpc
  • 368
  • 3
  • 15
0

Using the visible properties and asp literals provided in previous answers, I extended erionpc's answer to either display a 'no data' or record count.

<FooterTemplate>
                <asp:Literal ID="repeaterEmptyDataRow" runat="server" Visible='<%# Results_Repeater.Items.Count == 0 %>'>
                    <tr>
                        <td>No Data Found</td>    
                    </tr>
                </asp:Literal>
                <asp:Literal ID="repeaterResultsDataRow1" runat="server" Visible='<%# Results_Repeater.Items.Count != 0 %>'>
                    <tr>
                        <td>
                </asp:Literal>
                <asp:Literal ID="repeaterResultsDataRow2" runat="server" Visible='<%# Results_Repeater.Items.Count != 0 %>' Text='<%# String.Concat(Results_Repeater.Items.Count.ToString(), " records.") %>' />
                <asp:Literal ID="repeaterResultsDataRow3" runat="server" Visible='<%# Results_Repeater.Items.Count != 0 %>'>
                        </td>
                    </tr>
                </asp:Literal>
                </table>
            </FooterTemplate>

I don't write a lot of asp, so there maybe a cleaner way to do this.

Scott
  • 1
0

The best way I found to solve this :

  1. Add the following label anywhere on your page -

    <asp:Label ID="lblEmptyRepeater" runat="server" Visible="false" Text="There are no items in this repeater"></asp:Label>
    
  2. Add the OnPreRenderEvent for your Repeater

    <asp:Repeater ID="emptyRepeater" runat="server" OnPreRender="emptyRepeater_PreRender">
    
  3. Now inside this event in your codebehind, write the code

    protected void emptyRepeater_PreRender(object sender, EventArgs e)
    {
       lblEmptyRepeater.Visible = (emptyRepeater.Items.Count==0);
    }
    
  4. Now your empty repeater should be checked after the data is bound but before render on page, and show the label if it is empty.

rohithrrao
  • 21
  • 3