开发者

Databind repeater using Linq with group by

I need to bind a repeater with hierarchical data as follows:

Category1
   - Item1
   - Item2
Category2
   - Item3
   - Item4

I currently have a single dataset with the items as well 开发者_JS百科as the category that each item belongs to.

I'm trying to learn Linq and was wondering if there was a way I can do the same using Linq?

Below is what I tried:

var groupbyfilter = from dr in dtListing.AsEnumerable()
                            group dr by dr["Category"];
        DataTable dtFinal = dtListing.Clone();

  foreach (var x in groupbyfilter)
          x.CopyToDataTable(dtFinal, LoadOption.OverwriteChanges);


  rptList.DataSource = dtFinal;
  rptList.DataBind();

But trouble with it is it repeats category for each item.


You'll need a repeater nested inside another.

Do a distinct on the dtlisting selecting only the category field. Bind this to the outer repeater.

In the 2nd repeater, select data whose where condition has category field which equals to the value that is being databound to the repeater item. You'd have to handle this in the repeater's onitem_databound event.

Here is an example.

<%@ Import  Namespace="System.Data" %>
      <asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
          <ItemTemplate>
              <div>
                  Category: <b><%# Container.DataItem%></b>
                  <asp:Repeater ID="Repeater2" runat="server">
                      <FooterTemplate>
                          <%="</ul>" %>
                      </FooterTemplate>
                      <HeaderTemplate>
                          <%= "<ul>"%>
                      </HeaderTemplate>
                      <ItemTemplate>
                          <li>
                              <%# ((Data.DataRow)Container.DataItem)[1] %>, <%#  ((Data.DataRow)Container.DataItem)[0] %>
                          </li>
                      </ItemTemplate>
                  </asp:Repeater>
              </div>                
          </ItemTemplate>
      </asp:Repeater>

For this sample I used a csv as my datasource, and created a datatable using it. So my codebehind looks like:

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;

public class _Default : System.Web.UI.Page
{
    DataTable csvData;
    protected void Page_Load(object sender, System.EventArgs e)
    {
        csvData = Utils.csvToDataTable("data.csv", true);
        GridView1.DataSource = csvData;
        GridView1.DataBind();

        Repeater1.DataSource =
            (from x in csvData.AsEnumerable() select x["category"]).Distinct();
        Repeater1.DataBind();
    }

    protected void Repeater1_ItemDataBound(object sender, System.Web.UI.WebControls.RepeaterItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Item |
                e.Item.ItemType == ListItemType.AlternatingItem) {
            Repeater rptr = (Repeater)e.Item.FindControl("Repeater2");
            rptr.DataSource =
                csvData.AsEnumerable().Where(x => x["category"].Equals(e.Item.DataItem));
            rptr.DataBind();
        }
    }       
}


You can either use nested repeaters like deostroll says, or specify a grouping field and have a group header in your ItemTemplate that's dynamically hidden (or rendered) every time your grouping field changes.

More detail in fernan's answer at http://forums.asp.net/t/1252235.aspx

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜