空 Repeater 控件的默认文本

55

使用VS 2008,我有一个Repeater控件:

<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>

如果数据源从数据库返回的项为空,我希望显示一个默认文本,比如“未找到任何店铺”。迄今为止,我主要使用 GridView,因为它有 EmptyDataText 属性,所以没有遇到问题。

8个回答

82

Joaos的答案可以进一步简化。在页脚中,不要将默认项的visible属性设置为false,而是使用以下表达式:

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

这样,您就可以保存代码背后的内容。


哪个元素应用了 Visible 属性? - PreguntonCojoneroCabrón

31

另一种可能性:

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

这段代码片段的好处在于你不需要依赖于你分配给重复器的ID。


如果在“FooterTemplate”中我有“</table>”? - PreguntonCojoneroCabrón
1
@PreguntonCojoneroCabrón:尝试这个:<asp:Literal runat="server" Visible='<%# ((Repeater)Container.NamingContainer).Items.Count == 0 %>'> </table> </asp:Literal> - brz
这是一个好主意,但出于某些原因,我无法在页脚中绑定可见属性,我一直收到空引用异常。即使只是执行Visible="<%# true %>"也会抛出空引用异常。尝试在标签和文字上进行操作,结果相同。 - naasking

27
您可以通过在使用OnItemDataBound事件时结合FooterTemplate来解决Repeater控件不支持内置方式实现您正在执行的操作的事实,并仅在数据源不返回任何项时显示页脚,以此来规避问题。
关于如何执行此操作的示例可在以下链接中找到:
- 处理ASP.NET Repeater控件中的空数据 http://www.dotnetcurry.com/ShowArticle.aspx?ID=271 - 如何在ASP.NET Repeater控件中显示空模板? http://www.mindfiresolutions.com/How-to-show-Empty-Template-in-ASPNET-Repeater-control-1102.php

@marquito 如果你对语义不一致感到难过,你可以使用一个 Panel,并在 OnItemDataBound 中显示/隐藏它,而不是使用 FooterTemplate... - pseudocoder
@pseudocoder,这种悲伤来自于缺乏一种开箱即用的方法来解决它。此外,我被迫检查每个数据绑定项,以检查最终结果是否为空。还应该有一个“OnFinishedDataBinding”事件,可以防止不必要的调用OnItemDataBound。 - marquito
在尝试了几种不同的方法后,我成功地使用了这种方法。我认为在label的位置使用panel会增加更多的灵活性,我也期待着尝试一下。感谢分享! - Dylan Kinnett
我希望你现在已经知道了,但仅提供链接的答案有点糟糕... - Ortund
1
@Ortund 这不是一个仅有链接的答案。它涵盖了基本思路并提供了示例链接,这是可以接受的。然而,它并不是一个特别好的答案,但也远非应该删除。如果你觉得需要的话,可以给答案点个踩,并请阅读 https://meta.stackexchange.com/q/225370/332043。 - Zoe stands with Ukraine
显示剩余3条评论

7
更好的是:这个子类添加了一个EmptyDataTemplate属性。在你的标记中,像使用div元素一样添加一个空数据模板元素。默认情况下,如果没有数据,它将隐藏标题和页脚;你可以在标记中使用HeaderVisibleWhenEmpty和FooterVisibleWhenEmpty属性来更改这个设置。
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;
                }
            }
        }
    }
}

标记中的示例:

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

请注意,必须调用DataBind方法,否则空数据模板将不会显示。

1
你可以使用页脚模板来管理信息,就像这样:
第 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> 

步骤2

在Repeater_ItemDataBound事件中处理标签的可见性,例如:

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;
    }
  }
}

0

利用之前回答中提供的可见属性和asp文字,我扩展了erionpc的答案,以便显示“无数据”或记录计数。

<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>

我不怎么写asp,所以可能有更简洁的方法来实现这个。


Results_Repeater 是什么? - PreguntonCojoneroCabrón

0

基于第三个答案,我采用了以下解决方案,这对我来说似乎足够好:

<asp:Literal ID="emptyDataRowCnt" runat="server" Visible='<%# MyRepeater.Items.Count == 0 %>'>
    <li class="row emptyDataRow">No data here</li>
</asp:Literal>

0
我发现解决这个问题的最佳方法是:
  1. 在您的页面上任何位置添加以下标签 -

    <asp:Label ID="lblEmptyRepeater" runat="server" Visible="false" Text="There are no items in this repeater"></asp:Label>
    
  2. 为您的 Repeater 添加 OnPreRenderEvent

    <asp:Repeater ID="emptyRepeater" runat="server" OnPreRender="emptyRepeater_PreRender">
    
  3. 现在,在您的代码后台中,编写以下代码:

    protected void emptyRepeater_PreRender(object sender, EventArgs e)
    {
       lblEmptyRepeater.Visible = (emptyRepeater.Items.Count==0);
    }
    
  4. 现在,在数据绑定但在页面呈现之前检查空的 Repeater,并在其为空时显示标签。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接