How can I hide a repeater in ASP.NET C# if the Dat

2019-02-13 07:57发布

问题:

I have an ASP.NET page that uses a repeater nested within another repeater to generate a listing of data. It's to the effect of the following:

<asp:Repeater>
    <ItemTemplate>
        <span><%#Eval("Data1") %></span>
        <!-- and many more -->
        <asp:Repeater DataSource='<%#Eval("Data2")%>'>
            <HeaderTemplate>
                <ul>
            </HeaderTemplate>
            <ItemTemplate>
                <li><%#Container.DataItem%></li>
            </ItemTemplate>
            <FooterTemplate>
                </ul>
            </FooterTemplate>
        </asp:Repeater>
    </ItemTemplate>
</asp:Repeater>

In the (C#) code-behind I'm basically using LINQ to pull a listing of information from an XML document and bind that information to the first repeater.

Searching for the answer to this, it seems the method is to determine whether the data for the nested repeater is empty. If it is, then you set the visibility of the repeater to false.

Unfortunately, I haven't been able to determine how to do that inline, and not in the code-behind (since it won't necessarily work for what I'm doing).

Since my pages aren't validating now, because the ul ends up being empty for any items without Data2, and because I'd like to keep using an unordered list, I seek your help.

Any ideas?

Thanks!

UPDATE:

If it helps, since it could very well be possible to do in the code-behind, the LINQ is something to this effect:

var x = from y in z
    select new {
        Data1 = d,
        // etcetera
        Data2 = (from j in k
            where j.Value != String.Empty
            select j.Value).ToList()
    };

blah.DataSource = x;
blah.DataBind();

回答1:

This won't hide the repeater completely, but you can subclass the Repeater control so that it includes a GridView-like empty data template:

using System;
using System.Web.UI;
using System.Web.UI.WebControls;

public class EmptyCapableRepeater : Repeater
{
    public ITemplate EmptyDataTemplate { get; set; }

    protected override void OnDataBinding ( EventArgs e )
    {
        base.OnDataBinding( e );

        if ( this.Items.Count == 0 )
        {
            EmptyDataTemplate.InstantiateIn( this );
        }
    }
}

You can them use it in your .aspx like this:

<custom:EmptyCapableRepeater runat="server" ID="rptSearchResults">
    <ItemTemplate>
        <%# Eval( "Result" )%>
    </ItemTemplate>
    <SeparatorTemplate>
        <br />
    </SeparatorTemplate>
    <EmptyDataTemplate>
        <em>No results were found.</em>
    </EmptyDataTemplate>
</custom:EmptyCapableRepeater>


回答2:

Try something like:

<asp:Repeater runat="server" DataSource='<%#Eval("Data2")%>' 
    Visible='<%# ((IEnumerable)Eval("Data2")).GetEnumerator().MoveNext() %>'>

for the nested repeater



回答3:

Why not use a ListView? It offers much of the same functionality including an EmptyDataTemplate.



回答4:

use this:

protected void Repeater1_PreRender(object sender, EventArgs e)
{
    if (Repeater1.Items.Count < 1)
    {
        container.Visible = false;
    }
}


回答5:

When you get your LINQ query executed, check its Count property (providing its a list of some sort). If its 0, then just turn the Visible property to false.



回答6:

As far as I know you must do this via the codebehind, just use the ItemDataBound event to handle it, you can leave pretty much everything as is, just simply input some logic that gets the dataset and determines if it has entries, if not hide the repeater.



回答7:

I don't think what you are doing is going to work I get an error when I try and set the DataSource as you are trying to do; however, in the code behind you do this:

Assuming you added a listener to your parent repeater's ItemDataBoundEvent, then you will need to change your linq query slightly to not use an anonymous type (Create a protected class that has your properties) In mjy case I am using dto as the class name.

void rep1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{

    Repeater rep2 = (Repeater)e.Item.FindControl("rep2");
    rep2.DataSource = ((dto)e.Item.DataItem).y;
    rep2.DataBind();
}

I'd love to learn why you think you can't solve this in the code behind.



回答8:

I know this is an old thread and the answer above is a very nice solution, but I had a similar problem and have found another vary simple solution I thought I would share also. This validates just fine and displays the same.

Just change your footer template to:

<FooterTemplate> 
            <li style="display:none;">This will not show.</li></ul> 
</FooterTemplate> 

Or if your using tables:

<FooterTemplate> 
            <tr> style="display:none;"><td>But something must be in here.</td></tr></table> 
</FooterTemplate> 

Hope that helps someone!



回答9:

In the OnItemDataBound event, set visibility to false if ItemType is a Header and set visibility to true if ItemType is an Item.