在单个DataGridView中显示来自多个DataTable的行

时间:2014-11-17 09:18:26

标签: c# winforms datagridview datatable

我继承了多个具有不同列名的DataTable,这些列名目前都在他们自己的DataGridViews中显示。我想创建一个新的附加DataGridView,它将在一个DataGridView中显示它们。例如(非常简化):

public class DataTableA: DataTable
{
    public DataTableA()
    {
        this.Columns.Add("DateA", typeof(string));
        this.Columns.Add("PriceA", typeof(string));
        this.Columns.Add("SomeOtherFieldA", typeof(string));
    }
}

public class DataTableB: DataTable
{
    public DataTableB()
    {
        this.Columns.Add("DateB", typeof(string));
        this.Columns.Add("PriceB", typeof(string));
        this.Columns.Add("SomeOtherFieldB", typeof(string));
    }
}

我想在单个列中显示DataTableA.DateA和DataTableB.DateB中的值,并在新DataGridView的单个列中显示DataTableA.PriceA和DataTableB.PriceB中的值。我一直在探索制作一个共同的基类或接口,但还没有太多运气。在不更改列名(不是选项)的情况下,是否可以创建一个能够在同一列中显示的绑定?

修改
不幸的是,我认为简单地将DataTable合并或聚合到一个新的DataTable中是行不通的,因为系统的设计使得DataTableX类中的逻辑(例如,DataTableA和DataTableB)能够处理推送数据并更新相应的行。 DataTable。

另外,我不是试图将多个DataTable中的合并为一行,我试图在DataGridView的单个列中显示具有不同名称的多个列。例如,假设有这样的数据:

DataTableA:

DateA       PriceA  SomeOtherFieldA
20141118    2.0      a
20141119    3.0      b

DataTableB:

DateB       PriceB  SomeOtherFieldB
20141118    4.0      c
20141119    5.0      d

我想在DataGridView中显示以下内容:

Date        Price  
20141118    2.0 
20141119    3.0 
20141118    4.0 
20141119    5.0 

1 个答案:

答案 0 :(得分:0)

我最终使用Tarik的提示并将目标数据从原始源表复制到目标目标表,然后当通过推送数据更新源表时,我更新目标表中的相应数据。下面是一些示例代码,用于说明我是如何做到的。

注意:在我的代码中,我将流程称为“反映”源表中的数据到目标表,因为在目标表中只显示了源表的反映数据,不要与对象反射混淆,这是完全不相关的。

复制数据:

首先,我创建了字典,将源列名映射到目标表列名。 (目标列名包含在List中,因为我需要将单个源列复制到多个目标列 - 如果您不需要这样做,则可以使用简单的字符串Dictionary。)例如:

Dictionary<string, List<string>> reflectedColumnsMapA = new Dictionary<string, List<string>>()
{
    { "DateA", new List<string>() { "Date" }},
    { "PriceA", new List<string>() { "Price" }},
};

Dictionary<string, List<string>> reflectedColumnsMapB = new Dictionary<string, List<string>>()
{
    { "DateB", new List<string>() { "Date" }},
    { "PriceB", new List<string>() { "Price" }},
};

接下来,我创建了一个字典,将原始源表行映射到目标表行,用于保持行的同步。

Dictionary<DataRow, DataRow> sourceToTargetRowMap = new Dictionary<DataRow, DataRow>();

然后我创建了一个方法将数据从源表复制到目标表,同时填充源到目标行字典。

public void ReflectRowsToTable(DataTable sourceTable, DataTable targetTable, Dictionary<string, List<string>> reflectedColumnsMap)
{
    foreach (DataRow originalRow in sourceTable.Rows)
    {
        DataRow newRow = targetTable.NewRow();

        foreach (KeyValuePair<string, List<string>> keyValue in reflectedColumnsMap)
        {
            foreach (string targetColumn in keyValue.Value)
                newRow[targetColumn] = originalRow[keyValue.Key];
        }

        sourceToTargetRowMap.Add(originalRow, newRow);
        targetTable.Rows.Add(newRow);
    }
}

保持数据同步:

最后,为保持数据同步,我将ColumnChanged事件处理程序添加到所有源表:

sourceTable.ColumnChanged += (s, e) =>
{
    // check if the updated column is one of the columns that were reflected
    if (reflectedColumnsMap.ContainsKey(e.Column.ColumnName))
    {
        // get the target row corresponding to the updated row in the source table
        DataRow reflectedRow = sourceToTargetRowMap[e.Row];
        // update the corresponding columns in the target table
        foreach (string targetColumn in reflectedColumnsMap[e.Column.ColumnName])
        {
            // update the value
            reflectedRow[targetColumn] = e.Row[e.Column.ColumnName];
        }
    }
};