【问题标题】:Distinct column value in C# DataTableC# DataTable 中的不同列值
【发布时间】:2019-05-13 12:59:10
【问题描述】:

我在 C# 中有一个如下所示的 DataTable。

ID | Name | foodEaten | amountEaten
1  | Sam  | Burger    |   3
2  | Jeff | Burger    |   2
3  |Steve | Burger    |   1
4  |Clive | Mcdonalds |   4   
5  |Mike  | KFC       |   12 
6  |Cliff | KFC       |   5

我试图通过使用 webforms 将其基本上输出到 HTML。问题是,输出总是会有所不同,但它总是需要对 foodEaten 进行分组。

我所追求的基本上是一种将结果分组到 foodEaten 列上的方法,然后写出那些在下面吃过食物的人。我只需要指出如何将其动态分配给 asp:repeater 的正确方向。或类似的东西。

理想情况下它在页面上应该是这样的 -

 <h3> Burger(3)<h3>
 <p> Sam - 3 <p>
 <p> Jeff - 2 <p>
 <p> Steve - 1 <p> 

谢谢

山姆

编辑 -

我现在有一个不同的值数据表,其中包含不同的 foodEaten 值!现在来研究如何比较。

编辑2 -

我现在有一个数据集,其中包含不同的“foodEaten”值作为表名,以及每个表中的相应行,基于 foodEaten 列。现在我只需要将它动态绑定到中继器!

【问题讨论】:

  • 您所说的“现在要弄清楚如何比较”是什么意思?你在比较什么?
  • 不同值表和完整表!
  • 您熟悉嵌套中继器吗?您可以将一个中继器用于 foodEaten 组(例如:Burger (3)),然后使用嵌套中继器循环遍历吃该食物的人。您可能需要创建一个对象来存储列表,而不仅仅是使用数据集。
  • 我想过这个,但是我不会有这个不是动态的问题吗?我不需要硬编码表名之类的吗?
  • 查看我的更新答案。你不需要一个对象,你仍然可以是完全动态的。偷偷摸摸的东西。

标签: c# loops datatable


【解决方案1】:

我会使用 LINQ,因为它比在循环中编写逻辑更简洁。

var groupedDT = dataTable.AsEnumerable()
                .GroupBy(x => x.Field<string>("foodEaten"))
                .Select(o => new
                {
                    food = o.Key,
                    personsCount = dataTable.AsEnumerable().Where(row => row.Field<string>("foodEaten") == o.Key).ToList().Count
                })
                .ToList();

这将为您返回一份所吃的不同食物的列表,其中包含一个嵌套列表,其中包含吃该食物的人的数量以及他们吃的量。您可以通过执行groupedDT[ foodIndex ].dataRows[ personIndex ]["Name"] 之类的操作来循环访问数据(例如名称)。希望这会有所帮助。

================================================ ======================

** 编辑:更新以显示如何将其馈送到嵌套中继器。

您需要向主中继器添加一个 ondatabound 事件。然后,当您绑定转发器时,每个项目都会触发嵌套转发器绑定。见下文。注意:我还调整了 LINQ 以对数据表进行分组,这样您就可以获得人数(上图)。

aspx:

<asp:Repeater runat="server" ID="repFood" OnItemDataBound="repFood_ItemDataBound">
    <ItemTemplate>

        <h3><%# Eval("food") + " (" + Eval("personsCount") + ")" %></h3>
        <asp:HiddenField runat="server" ID="hfFoodEaten" Value='<%# Eval("food") %>' />

        <asp:Repeater runat="server" ID="repPersons">
            <ItemTemplate>
                <p><%# Eval("[\"Name\"]") +  " - " + Eval("[\"amountEaten\"]") %></p>
            </ItemTemplate>
        </asp:Repeater>

    </ItemTemplate>
</asp:Repeater>

代码隐藏:

绑定主中继器:

repFood.DataSource = groupedDT;
repFood.DataBind();      

ondatabound 事件:

protected void repFood_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    var hfFoodEaten = e.Item.FindControl("hfFoodEaten") as HiddenField;
    var repPersons = e.Item.FindControl("repPersons") as Repeater;
    var dataSource = ViewState["DataTable"] as DataTable;

    repPersons.DataSource = dataSource.AsEnumerable().Where(row => row.Field<string>("foodEaten") == hfFoodEaten.Value).ToList();
    repPersons.DataBind();
}

向主中继器项目添加隐藏字段是将foodEaten 变量传递给嵌套中继器的简单方法。使用它来获取食物匹配的数据行。然后从 aspx 中,使用 Eval 获取 ID、名称、amountEaten 或任何您需要的内容。希望这会有所帮助。

【讨论】:

    【解决方案2】:

    如果性能不是问题,您可以将该表强制转换为 Enumerable,然后在其上使用 Linq。像这样的:

    var result = table.AsEnumerable().GroupBy(row => row["Food"]).Select(grp => new
    {
        Food = grp.Key,
        Eaten = grp.Sum(eaten => (int)eaten["amountEaten"])
    });
    
    
    foreach (var grp in result)
    {
        log($"{grp.Food}  ->  {grp.Eaten}");                
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-02
      • 2013-03-17
      • 2018-06-17
      • 1970-01-01
      相关资源
      最近更新 更多