Handling Empty Data in an ASP.NET Repeater control

Posted by: Suprotim Agarwal , on 2/12/2009, in Category ASP.NET
Views: 164115
Abstract: The GridView has an EmptyDataText property or the that lets us handle EmptyData. However the Repeater has no such property or template. In this article, we will see how to adopt a simple technique to handle empty data in an ASP.NET Repeater control without creating a custom control.
Handling Empty Data in an ASP.NET Repeater control
 
The GridView has an EmptyDataText property or the <EmptyDataTemplate> that lets us handle EmptyData. However the Repeater has no such property or template. In this short article, we will see how to adopt a simple technique to handle empty data in an ASP.NET Repeater control without creating a custom control.
Drag and drop a Repeater and a SQLDataSource control to the page. Bind the Repeater to the SQLDataSource as you usually do
<div>
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1"            
    onitemdatabound="Repeater1_ItemDataBound">
 <HeaderTemplate>
    <table border="1" cellpadding="3" cellspacing="3">
    <tr bgcolor="blue">
    <td><b>CustomerID</b>
    </td>
    <td><b>CompanyName</b>
    </td>
    <td><b>ContactName</b>
    </td>
    <td><b>ContactTitle</b></td>
    </tr>
</HeaderTemplate>
 <ItemTemplate>
     <tr>
     <td>
        <%#DataBinder.Eval(Container.DataItem, "CustomerID")%>
     </td>
     <td>
        <%#DataBinder.Eval(Container.DataItem, "CompanyName")%>   
     </td>
     <td>
        <%#DataBinder.Eval(Container.DataItem, "ContactName")%>   
     </td>
     <td>
        <%#DataBinder.Eval(Container.DataItem, "ContactTitle")%>   
     </td>
     </tr>
 </ItemTemplate>
 <FooterTemplate>
 </table>           
 </FooterTemplate>
 
</asp:Repeater>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
    ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
    SelectCommand="SELECT [CustomerID], [CompanyName], [ContactName],
    [ContactTitle], [Address] FROM [Customers] " >
</asp:SqlDataSource>
</div>
In your web.config, add a connection string as shown below:
 
      <connectionStrings>
            <add name="NorthwindConnectionString" connectionString="Data Source =(local);Integrated Security = SSPI; Initial Catalog=Northwind;"/>
      </connectionStrings>
 
If you run the application, the repeater would display the data from the database. Now change the query so that it returns empty data.
SELECT [CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address] FROM [Customers] WHERE CUSTOMERID=’XYZ’
 
On running the application, you would see the following:
Empty Data
Now this display is not elegant enough to inform the user that there is no data, right? So let us see how to display a message in the Repeater control when there is no data present.
In the <FooterTemplate>, add a Label with some empty data text and set its visible property to false.
<FooterTemplate>
 <tr>
 <td>
 <asp:Label ID="lblEmptyData"
        Text="No Data To Display" runat="server" Visible="false">
 </asp:Label>
 </td>
 </tr>
 </table>           
 </FooterTemplate>
Now add an ItemDataBound event to the Repeater
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1"            
    onitemdatabound="Repeater1_ItemDataBound">
In the code behind, write the following code:
C#
    protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if (Repeater1.Items.Count < 1)
        {
            if (e.Item.ItemType == ListItemType.Footer)
            {
                Label lblFooter = (Label)e.Item.FindControl("lblEmptyData");
                lblFooter.Visible = true;
            }
        }
    }
VB.NET
      Protected Sub Repeater1_ItemDataBound(ByVal sender As Object, ByVal e As RepeaterItemEventArgs)
            If Repeater1.Items.Count < 1 Then
                  If e.Item.ItemType = ListItemType.Footer Then
                        Dim lblFooter As Label = CType(e.Item.FindControl("lblEmptyData"), Label)
                        lblFooter.Visible = True
                  End If
            End If
      End Sub
The code checks if the Repeater has items in it. If the items count is less than 1, the code uses the FindControl() to locate the label and set it to visible.
On running the application again, you get to see the message 'No Data To Display' as shown in the screenshot below. This is certainly more user friendly than letting the user wonder why the data was not displayed at the first place.
Empty Data Message
I hope this article was useful and I thank you for viewing it. If you liked the article,  Subscribe to the RSS Feed or Subscribe Via Email 
What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of DotNetCurry, DNC Magazine for Developers, SQLServerCurry and DevCurry. He has also authored a couple of books 51 Recipes using jQuery with ASP.NET Controls and a new one recently at The Absolutely Awesome jQuery CookBook.

Suprotim has received the prestigious Microsoft MVP award for nine times in a row now. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that represents premium web sites and digital publications comprising of Professional web, windows, mobile and cloud developers, technical managers, and architects.

Get in touch with him on Twitter @suprotimagarwal, LinkedIn or befriend him on Facebook



Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by CaMeL on Thursday, February 12, 2009 8:44 PM
Thanks for great code ! I needed something like that :)
Comment posted by Yogesh on Friday, February 13, 2009 1:11 AM
Thanks,
It's very good idea.
I like this coading...
Comment posted by Lod Lawson on Thursday, March 5, 2009 12:53 PM
thanks a lot for this one.really helped
spent an hour trying to figure out how to
display a simple feed back message when no data is found
thanks very much
Comment posted by Matt on Friday, May 29, 2009 3:48 PM
I think it would be better to show/hide the whole [tr] row, otherwise when there is data, you have an empty row just sitting there.  That can be acheived by [tr id="myNoDataRow" runat="server"] then finding that control instead of the Label in the code-behind.
Comment posted by Thanigainathan on Sunday, May 31, 2009 2:41 AM
Hi,

Very nice post. Thanks for noting down the footer template .

Thanks,
Thani
Comment posted by kumar on Sunday, May 31, 2009 4:46 AM
Some times we don't have data in our table but what to do with this emptyness so it useful to show some message like this
Comment posted by Shail on Sunday, May 31, 2009 1:06 PM
Good one
Comment posted by Jit on Tuesday, September 22, 2009 7:48 AM
Nice tutorial,
i like the idea of footer template.
i got one more tutorial at below URL which is also working well.

http://shivasoft.in/view_tutorial.php?id=100



Comment posted by Ian on Thursday, November 26, 2009 11:50 AM
I use something like:

    protected void rptTerritories_PreRender(object sender, EventArgs e)
    {
        Repeater rpt = (Repeater)sender;
        if (rpt.Items.Count == 0)
            rpt.Controls.Add(new LiteralControl("No territories selected."));
    }
Comment posted by Ian on Thursday, November 26, 2009 11:55 AM
(edit: obviously above wont work if you have header or footer templates)
Comment posted by Ian on Thursday, November 26, 2009 12:20 PM
Try somthing like this if you dont want the table header shown:

.aspx:

...
<asp:Repeater ID="rptDateWindows" runat="server" DataSource='<%# Eval("NonNullDateWindows") %>'
OnPreRender="rptDateWindows_PreRender">
<HeaderTemplate>
  <table>
    <tr id="DateWindowHeader" runat="server">
...
(etc)


.aspx.cs:

    protected void rptDateWindows_PreRender(object sender, EventArgs e)
    {
        Repeater rpt = (Repeater)sender;
        if (rpt.Items.Count == 0)
        {
            Control c = (Control)this.FindControlRecursive("DateWindowHeader", rpt);
            c.Visible = false;

            rpt.Controls.Add(new LiteralControl("No date windows selected."));
        }
    }


where the 'FindControlRecursive' method penetrates NamingContainer boundaries (I cant remember where I got it - google for it, its quite useful). You need a recursive find because the Header template is a naming container.

cheers
Comment posted by Brian Maddox on Saturday, December 5, 2009 7:42 PM
On a similar note, you can hide items within the repeater if they have no data through the method described at http://blog.evonet.com.au/post/2009/12/04/Hiding-table-rows-in-a-repeater.aspx
Comment posted by Brian Maddox on Saturday, December 5, 2009 7:43 PM
On a similar note, you can hide items within the repeater if they have no data through the method described at

<a href="http://blog.evonet.com.au/post/2009/12/04/Hiding-table-rows-in-a-repeater.aspx">http://blog.evonet.com.au/post/2009/12/04/Hiding-table-rows-in-a-repeater.aspx</a>
Comment posted by Swapnil Agrawal on Tuesday, August 17, 2010 5:39 PM
Thats exactly what i wanted , really helped and liked the footer concept , so easy and simple.
Comment posted by shekhar r gurav on Thursday, September 23, 2010 8:49 AM
Thanks...
Very good Article
Comment posted by Steven on Monday, December 6, 2010 1:53 PM
Does this code work? I get different results. I have an item template and a footer template like the one above that is supposed to get displayed if items.count < 1. However, the itemDataBound method gets called twice, once with repeater.Items.Count == 0 and e.ItemType = Item and then with Items.Count == 1 with e.ItemType == 1.

I am confused as to why your xml seems to be not well formed. You end your table tag within the footertemplate. I tried this, and I get different results. Items.Count was 0 each time my ItemDataBound method was called. I either have one record or none and I want to display the footer, if there are no records. i.e. there are no items. I have read other places where you can't get the number of rows returned from the datasource from the repeater itself. The code that I am trying to fix looks just like yours but it does not work. I didn't write it, but I suspect that person that did got it from an example just like yours.

It does not really make sense that the repeater.items.count property is the number of rows returned in the datasource connected to the repeater if the item type can be header, item, or footer.
Comment posted by Steven on Monday, December 6, 2010 1:56 PM
I have one correction to my post above. I meant to say e.IemType=Footer instead of e.ItemType = 1 so it should read:

However, the itemDataBound method gets called twice, once with repeater.Items.Count == 0 and e.ItemType = Item and then with Items.Count == 1 with e.ItemType == footer.

Comment posted by Steven on Monday, December 6, 2010 2:07 PM
I have one correction to my post above. I meant to say e.IemType=Footer instead of e.ItemType = 1 so it should read:

However, the itemDataBound method gets called twice, once with repeater.Items.Count == 0 and e.ItemType = Item and then with Items.Count == 1 with e.ItemType == footer.

Comment posted by Jason Cartwright on Saturday, November 26, 2011 7:04 AM
Hey man, thanks heaps for this post. I'd been trying for hours to get this problem sorted. I knew it was just a matter of finding the right site, yours was it. Much appreciated.
Comment posted by Suprotim Agarwal on Sunday, November 27, 2011 8:59 PM
Jason: Glad this post helped you out! Thanks for the feedback
Comment posted by James Hendrix on Tuesday, May 22, 2012 3:50 PM
I've spent too many hours working on a solution for the empty data and your example took care of the issue. Thanks.
Comment posted by Waleed on Thursday, May 31, 2012 2:16 AM
This article is very useful for me, Thanxx
Comment posted by Ted on Tuesday, June 5, 2012 6:57 AM
Sorry, but your solution is completely wrong simply because the show/hide code will be executed for EVERY ITEM in the repeater...
Comment posted by Ted on Tuesday, June 5, 2012 7:13 AM
The following code runs only once:
protected void rpResults_PreRender(object sender, EventArgs e)
    {
        if (rpResults.Items.Count == 0)
        {
            System.Web.UI.HtmlControls.HtmlTableRow tr = (System.Web.UI.HtmlControls.HtmlTableRow)rpResults.Controls[rpResults.Controls.Count - 1].Controls[0].FindControl("trFooter");
            tr.Visible = true;
        }
    }
Comment posted by Peter on Saturday, June 23, 2012 11:06 PM
Yea, better to change it to:

                    <FooterTemplate>
                        <tr id="myNoDataRow" runat="server">
                            <td>Booking has no notes</td>
                        </tr>
                        </table>          
                    </FooterTemplate>

    protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Footer)
        {
            System.Web.UI.HtmlControls.HtmlTableRow myNoDataRow = (System.Web.UI.HtmlControls.HtmlTableRow)e.Item.FindControl("myNoDataRow");
            myNoDataRow.Visible = this.lstNotes.Items.Count == 0;
        }
    }
Comment posted by Bruno Garcia on Friday, August 17, 2012 2:37 AM
Better solution would be replacing Repeater with ListView and add EmptyDataTemplate

http://blog.brunogarcia.com
Comment posted by rock on Sunday, December 9, 2012 4:36 PM
私はモンクレールのダウン街で最高のジャケットを持っていると思う。私は本当にモンクレールが好きで、私はできる、私はできるだけ多くの得ることがしたい。 :D
<a href="http://www.moncleroutlet2013japan.com">モンクレール ダウン</a>
Comment posted by jkjh on Tuesday, July 30, 2013 12:23 AM
jkjkjk
Comment posted by Rohit Choudhury on Saturday, August 24, 2013 7:19 AM
Fantastic...I just used it as it was..Not even have to change a single letter...Awesome...
Comment posted by karthik on Wednesday, December 17, 2014 9:55 PM
Thanks Very Much

Categories

JOIN OUR COMMUNITY

POPULAR ARTICLES

FREE .NET MAGAZINES

Free DNC .NET Magazine

Tags

JQUERY COOKBOOK

jQuery CookBook