在转发器中显示一次类别

Display category once in repeater

我有一个中继器想要显示类别和产品。类别应该出现一次,产品会出现我拥有的产品数量。下面是我的标记

<asp:Repeater ID="rpt1" runat="server" OnItemDataBound="rpt1_ItemDataBound">
    <ItemTemplate>
        <asp:Label ID="lblCategory" runat="server"></asp:Label>
        <asp:Label ID="lblProductName" runat="server"></asp:Label>
    </ItemTemplate>
</asp:Repeater>

我在页面加载时绑定产品

if (!Page.IsPostBack)
{
    LoadData();
}

我的代码隐藏

protected void rpt1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
        Product p = (Product)e.Item.DataItem;

        Label lblCategory = e.Item.FindControl("lblCategory") as Label;
        Label lblProductName = e.Item.FindControl("lblProductName") as Label;

        lblProductName.Text = p.ProductName;
        lblCategory.Text = p.Category.CategoryName;
    }
}

一切正常,但我的类别文本重复了不止一次(它显示了我拥有的产品数量)。我怎样才能只显示一次类别?

编辑

Cat 20 is Stationery
Cat 30 is Computer Items
Cat 40 is Toiletry

**Id CatId ProductName**
1   20     Pencil
1   20     Pen
1   30     Compact Disc
1   30     USB
1   30     Hard drive
1   40     Toothpaste
1   40     Toothbrush

我在

中获取数据
Iqueryable<Product> LoadData = myContext.GetProducts();

我认为在这种情况下使用嵌套中继器会更好。我的意思是 Categories 的第一个转发器和 Products 的嵌套转发器。参见:Nested repeater

<asp:Repeater runat="server" id="Categories">
  <ItemTemplate>
    Category: <%# Eval("CategoryName") %>
    Products:
    <asp:Repeater runat="server" DataSource='<%# Eval("Products") %>'>
      <ItemTemplate><%# Eval("ProductName") %></ItemTemplate>
    </asp:Repeater>
  </ItemTemplate>
</asp:Repeater>

但是要做到这一点你需要在数据模型上做一些工作,你的模型应该是这样的:

public class Category 
{
    public string CategoryName {get; set;}
    public IEnumerable<Product> Products {get; set;}
}

public class Product 
{
    public string ProductName {get; set;}
}

或者快速解决方案是通过将每个转发器项目的类别名称与上一行进行比较。如果更改类别名称则显示新的类别名称,否则设置为空:

protected void rpt1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
        Product p = (Product)e.Item.DataItem;

        Label lblCategory = e.Item.FindControl("lblCategory") as Label;
        Label lblProductName = e.Item.FindControl("lblProductName") as Label;

        lblProductName.Text = p.ProductName;

        if(e.Item.ItemIndex > 0)
        {
            RepeaterItem previousRepeaterItem = rpt1.Items[e.Item.ItemIndex - 1];
            var previousCategoryName = (previousRepeaterItem.FindControl("lblCategory") as Label).Text;
            if(previousCategoryName != p.Category.CategoryName)
            {
                lblCategory.Text = p.Category.CategoryName; 
            }
        }
    }
}

我不确定您要显示的产品数据的复杂程度。但我想建议您使用嵌套 Repeaters,一个中继器将具有类别名称,第二个将具有产品。在 Page_Load 上,您应该获取所有不同的类别并绑定第一个转发器。在第一个转发器的 ItemDataBound 上,您必须获取与该类别相关的产品并绑定嵌套的转发器。

例如:

<asp:Repeater ID="rpt1" runat="server" OnItemDataBound="rpt1_ItemDataBound">
    <ItemTemplate>
        <asp:Label ID="lblCategory" runat="server" Text='<%# Eval("Category") %>'></asp:Label>
        <asp:Repeater ID="rpt2" runat="server">
            <ItemTemplate>
                <asp:Label ID="lblProductName" runat="server" Text='<%# Eval("ProductName")%>'></asp:Label>
            </ItemTemplate>
        </asp:Repeater>
    </ItemTemplate>
</asp:Repeater>

页面加载:

protected void Page_Load(object s, EventArgs e)
{
    // Fetch All the Categories, Distinct Elements
    DataTable dt = new DataTable();
    dt.Columns.Add("Category");
    dt.Rows.Add("Sanatizers");
    dt.Rows.Add("Soaps");
    rpt1.DataSource = dt;
    rpt1.DataBind();
}

项目数据绑定:

protected void rpt1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
        Label lblCategory = (Label)e.Item.FindControl("lblCategory");

        Repeater rpt2 = (Repeater)e.Item.FindControl("rpt2");
        if (lblCategory != null)
        {
            // Fetch products by category
            var dt = new DataTable();
            dt.Columns.Add("ProductName");
            dt.Rows.Add("Dettol");
            dt.Rows.Add("Safeguard");
            dt.Rows.Add("Fair and Lovely");
            rpt2.DataSource = dt;
            rpt2.DataBind();
        }
    }
}

PS:代码未测试,可能需要一些爱。