Default text for empty Repeater control
asp.netRepeaterasp.net Problem Overview
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>
</td>
<td style="width:110px">
<asp:Label ID="storeLbl" runat="server" Text='<%# Bind("Name") %>'>
</asp:Label>
</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.
asp.net Solutions
Solution 1 - asp.net
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.
Solution 2 - asp.net
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.
Solution 3 - asp.net
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:
Solution 4 - asp.net
Even better: this subclass adds an EmptyDataTemplate property. In your markup, put in an
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.
Solution 5 - asp.net
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;
}
}
}
Solution 6 - asp.net
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>
Solution 7 - asp.net
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.
Solution 8 - asp.net
The best way I found to solve this :
-
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>
-
Add the OnPreRenderEvent for your Repeater
<asp:Repeater ID="emptyRepeater" runat="server" OnPreRender="emptyRepeater_PreRender">
-
Now inside this event in your codebehind, write the code
protected void emptyRepeater_PreRender(object sender, EventArgs e) { lblEmptyRepeater.Visible = (emptyRepeater.Items.Count==0); }
-
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.