【问题标题】:DataTable not keeping added valuesDataTable 不保留附加值
【发布时间】:2014-01-25 18:18:08
【问题描述】:

我对 C# 和 WPF 还很陌生,而且我的暴露主要是自己造成的,所以我认为我可能遗漏了一些明显的东西。然而,它似乎如此很明显,它没有在几个小时的搜索中出现。

由于我只是想弄清楚处理,所有数据都是任意的,简单的,有点傻。

我在一个名为 dt1 的 DataTable 中有这些数据:

Name   Count  Date
Fred   1      12/01/13
Fred   2      12/02/13
Fred   3      12/03/13
Fred   4      12/04/13
Barney 4      12/01/13
Barney 3      12/02/13
Barney 2      12/03/13
Barney 1      12/04/13
Wilma  1      12/01/13
Wilma  2      12/02/13
Wilma  3      12/03/13
Wilma  4      12/04/13
Betty  4      12/01/13
Betty  3      12/02/13
Betty  2      12/03/13
Betty  1      12/04/13

(列分别为string、int和string)

我要做的是创建第二个 DataTable,每个名称都有一行,每个日期的计数显示在单独的列中,因此:

Name  12/01/13  12/02/13  12/03/13  12/04/13
Fred  1         2         3         4
...

这是我用来填充第二个 DataTable 的代码:

DataTable dt2 = new DataTable();

//add columns for the target dates
dt2.Columns.Add("Name", typeof(string));
for (int n = 1; n < 5; n++)
{
    dt2.Columns.Add(String.Format("12/0{0}/13", n.ToString()), typeof(int));
}

DataRow pivotRow = dt2.NewRow();

foreach (DataRow row in dt1.Rows)   //step through the rows in the source table
{
    if (pivotRow[0].ToString() != row[0].ToString())   //if this is a "new" name in the data set
    {
        if (pivotRow[0].ToString() != "")  //and it's not the first row of the data set
            dt2.Rows.Add(pivotRow);  //add the row we've been working on
        pivotRow = dt2.NewRow();  //create a new row for the "next" name
        pivotRow[0] = row[0].ToString();  //add the "next" name to the name column
    }
    //match the string date stored in column 2 of the source DataTable to the column name in the target one, and put the associated int value in that column
    pivotRow[row[2].ToString()] = (int)row[1];
}
//once we've finished the whole source DataTable, add the final row to the target DataTable
dt2.Rows.Add(pivotRow);

//at this point, looking at it through the locals window everything *appears* to be peachy in dt2

GridView.ItemsSource = dt2.DefaultView;  //and here, it's all the pits.

这是在 DataGrid 中显示的内容:

Name        12/01/13    12/02/13    12/03/13    12/04/13
Fred
Barney
Wilma
Betty

显然 something 正在被保存,因为它保存了行首的名称,但同样明显的是它没有保存其余的数据点。

我的头骨因撞在这堵特殊的墙上而变得糊状,所以我决定向比我更了解(很多)的人寻求帮助。

我们将不胜感激任何见解或建议。

【问题讨论】:

    标签: c# wpf datagrid datatable datarow


    【解决方案1】:

    这是一个适用于原始数据表中任意日期和任意名称顺序的解决方案:

    DataTable dt2 = new DataTable();
    dt2.Columns.Add("Name", typeof(string));
    
    IEnumerable<DateTime> distinctDates = dt1.AsEnumerable().Select(row => (DateTime)row["Date"]).Distinct().OrderBy(date => date);
    foreach (var distinctDate in distinctDates)
    {
        dt2.Columns.Add(distinctDate.ToString("MM__dd__yy", CultureInfo.InvariantCulture), typeof(int));
    }
    
    IEnumerable<string> distinctNames = dt1.AsEnumerable().Select(row => (string)row["Name"]).Distinct();
    foreach (var distinctName in distinctNames)
    {
        DataRow outputRow = dt2.NewRow();
        outputRow["Name"] = distinctName;
    
        IEnumerable<Tuple<int, DateTime>> inputRowsForName = dt1.AsEnumerable()
            .Where(row => (string)row["Name"] == distinctName)
            .Select(row => new Tuple<int, DateTime>((int)row["Count"], (DateTime)row["Date"]));
    
        foreach (var inputRowForName in inputRowsForName)
        {
            string columnName = inputRowForName.Item2.ToString("MM__dd__yy", CultureInfo.InvariantCulture);
            outputRow[columnName] = inputRowForName.Item1;
        }
        dt2.Rows.Add(outputRow);
    }
    
    GridView.ItemsSource = dt2.DefaultView;
    

    【讨论】:

    • 我敢肯定,一旦我对 C# 有足够的能力让我觉得它对我有意义,我会发现它很有用!谢谢你。 :)
    • @NatCh 没问题。您可能不熟悉的部分是WhereSelect 等方法。这些是所谓的 LINQ 扩展方法,您可以使用它们以类似于使用 SQL 处理数据库表的方式来查询和操作列表。
    • 不,我很好地遵循了 LINQ/SQL 部分——我最近一直在使用这些部分。让我无法理解的是枚举、元组和 lambda 表达式。我认得它们,并且知道它们是什么,但还不足以遵循或使用它们。 (耸肩)
    • @NatCh IEnumerable&lt;T&gt; 只是一个支持对集合进行迭代的接口。你可以说IEnumerable&lt;int&gt; collection = new List&lt;int&gt;();,然后使用collection 变量进行迭代(在foreach 中)。我在这里使用它是因为这就是我所需要的,并且因为使用 List&lt;T&gt; 需要额外的 ToList() 操作来复制整个集合。
    • @NatCh Lambdas 是一种声明匿名函数的简洁方式。返回5:() =&gt; 5;正方形:x =&gt; x * x(x) =&gt; x * x;乘:(x, y) =&gt; x * y。如果右侧有多个表达式,则必须用 {} 将其括起来,如果需要返回值,则使用 return。愚蠢的例子:(x) =&gt; { int min = DateTime.Now.Minute; return min * 5; }。它们与 Linq 扩展方法齐头并进,可用于定义要为集合的每个元素执行的操作。 List&lt;int&gt; ints = new List&lt;int&gt; { 1, 2, 3 }; List&lt;int&gt; intSquares = ints.Select(x =&gt; x * x).ToList();
    【解决方案2】:

    如果您在调试时查看 输出 窗口,您应该会注意到当网格尝试显示您的数据时出现大量绑定错误。问题是“/”字符被用于解析与底层对象的绑定,因此它无法从您的视图中获取数据。

    您可以通过替换 ColumnName 中的 '/' 字符但将其放在 Caption 中来实现此功能。

    //add columns for the target dates
    DataTable dt2 = new DataTable();
    dt2.Columns.Add("Name", typeof(string));
    for (int n = 1; n < 5; n++)
    {                
        var dataColumn = dt2.Columns.Add(String.Format("12_0{0}_13", n), typeof (int));
        dataColumn.Caption = String.Format("12/0{0}/13", n);                
    }
    
    DataRow pivotRow = dt2.NewRow();
    
    foreach (DataRow row in dt1.Rows)   //step through the rows in the source table
    {
        if (pivotRow[0].ToString() != row[0].ToString())   //if this is a "new" name in the data set
        {
            if (pivotRow[0].ToString() != "")  //and it's not the first row of the data set
                dt2.Rows.Add(pivotRow);  //add the row we've been working on
            pivotRow = dt2.NewRow();  //create a new row for the "next" name
            pivotRow[0] = row[0].ToString();  //add the "next" name to the name column
        }
        //match the string date stored in column 2 of the source DataTable to the column name in the target one, replacing the '/', and put the associated int value in that column
        pivotRow[row[2].ToString().Replace("/", "_")] = (int)row[1];
    }
    //once we've finished the whole source DataTable, add the final row to the target DataTable
    dt2.Rows.Add(pivotRow);
    

    【讨论】:

    • 哦,为了小青苹果的爱。现在我比我预想的还要尴尬。谢谢,做到了。我只是将斜杠换成了连字符,它们可以很好地满足我的目的。另外,感谢您如此亲切地回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-30
    • 1970-01-01
    相关资源
    最近更新 更多