3

我从另一个数据表中获取值作为列表的输入。现在我需要将这些列表值保存到另一个 DataTable 中。

列表:

List<DataRow> list = slectedFieldsTable.AsEnumerable().ToList();
foreach (DataRow dr in slectedFieldsTable.Rows)
{
    list.Add(dr);
}

新数据表:

DataRow newRow = tempTable.NewRow();
newRow["Field Name"] = fieldLabel;
newRow["Field Type"] = fieldType;

for(int gg =0 ; gg<list.Count; gg++)
{
    tempTable.Rows.Add(????);
}

我被困在这里将行添加到新数据表中。

4

5 回答 5

8
public static DataTable ToDataTable<T>(List<T> items)
{
        DataTable dataTable = new DataTable(typeof(T).Name);

        //Get all the properties
        PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
        foreach (PropertyInfo prop in Props)
        {
            //Setting column names as Property names
            dataTable.Columns.Add(prop.Name);
        }
        foreach (T item in items)
        {
           var values = new object[Props.Length];
           for (int i = 0; i < Props.Length; i++)
           {
                //inserting property values to datatable rows
                values[i] = Props[i].GetValue(item, null);
           }
           dataTable.Rows.Add(values);
      }
      //put a breakpoint here and check datatable
      return dataTable;
}
于 2013-11-28T10:29:37.790 回答
6

变量声明:

    DataTable tempTable = new DataTable();
    DataTable slectedFieldsTable = new DataTable();
    DataRow newRow;
    List<object> list = new List<object>();

在数据表中添加列:

    slectedFieldsTable = new DataTable();
    slectedFieldsTable.Columns.Add("Field Name");
    slectedFieldsTable.Columns.Add("Field Type");

在 DataTable 中添加值:

    slectedFieldsTable.Rows.Add("1", "AAA");
    slectedFieldsTable.Rows.Add("2", "BBB");
    slectedFieldsTable.Rows.Add("3", "CCC");

将数据表转换为列表:

  foreach (DataRow dr in slectedFieldsTable.Rows)
    {
        list.Add(dr);
    }

在另一个数据表中添加列:

    tempTable.Columns.Add("Field Name", typeof(string));
    tempTable.Columns.Add("Field Type", typeof(string));

将列表转换为数据表:

   foreach(DataRow dr in list)
    {
        newRow = tempTable.NewRow();
        newRow["Field Name"] = dr.ItemArray[0].ToString();
        newRow["Field Type"] = dr.ItemArray[1].ToString();
        tempTable.Rows.Add(newRow);
        tempTable.AcceptChanges();
    }
于 2014-01-23T15:38:59.407 回答
2

使用 CopyToDataTable() 方法。 复制到数据表

IEnumerable<DataRow> query = TempselectedFieldsTable.AsEnumerable().ToList();

// Create a table from the query.
DataTable boundTable = query.CopyToDataTable<DataRow>();
于 2013-02-28T05:38:06.547 回答
2

提供的答案ToDataTable是一个非常好的开始,但它缺少一些关键要素。也就是说,它忽略了List项目属性可能:

  • ...被标记ReadOnly
  • ...使用DisplayName属性
  • ...有一个DefaultValue应该DataColumn知道的
  • ...是Nullable
  • ...被标记BrowsableAttribute(false)

以下是返回 a 的扩展方法DataTable,或者说明上述情况,或者为您的代码提供应用它们的方法。它还使用 anInterface从类对象中获取值,而不是Reflection.

public static DataTable ToDataTable<T>(this IList<T> lst, bool includeAll = true)
{
    DataTable dt = new DataTable();
    DataColumn dc;
    PropertyDescriptor pd;
    bool Browsable;

    PropertyDescriptorCollection propCol = TypeDescriptor.GetProperties(typeof(T));

    for (int n = 0; n < propCol.Count; n++)
    {
        pd = propCol[n];
        Type propT = pd.PropertyType;

        dc = new DataColumn(pd.Name);

        // if Nullable, get underlying type
        // the first test may not be needed
        if (propT.IsGenericType && Nullable.GetUnderlyingType(propT) != null )
        {
            propT = Nullable.GetUnderlyingType(propT);
            dc.DataType = propT;
            dc.AllowDBNull = true;
        }
        else
        {
            dc.DataType = propT;
            dc.AllowDBNull = false;
        }

        // is it readonly?
        if (pd.Attributes[typeof(ReadOnlyAttribute)] != null)
        {
            dc.ReadOnly = ((ReadOnlyAttribute)pd.
                     Attributes[typeof(ReadOnlyAttribute)]).IsReadOnly;
        }         

        // DefaultValue ...
        if (pd.Attributes[typeof(DefaultValueAttribute)] != null)
        {
            dc.DefaultValue = ((DefaultValueAttribute)pd.
                   Attributes[typeof(DefaultValueAttribute)]).Value;
        }

        // caption / display name
        dc.ExtendedProperties.Add("DisplayName", dc.Caption);
        if (pd.Attributes[typeof(DisplayNameAttribute)] != null)
        {
            // these are usually present but blank
            string theName = ((DisplayNameAttribute)pd.
                   Attributes[typeof(DisplayNameAttribute)]).DisplayName;
            dc.Caption = string.IsNullOrEmpty(theName) ? dc.Caption : theName;
            // DGV doesnt use Caption...save for later
            dc.ExtendedProperties["DisplayName"] = dc.Caption;
        }

        Browsable = true;
        dc.ExtendedProperties.Add("Browsable", Browsable);
        var foo = pd.Attributes[typeof(BrowsableAttribute)];
        if (pd.Attributes[typeof(BrowsableAttribute)] != null) 
        {
            Browsable = ((BrowsableAttribute)pd.Attributes[typeof(BrowsableAttribute)]).Browsable;
            // no such thing as a NonBrowsable DataColumn
            dc.ExtendedProperties["Browsable"] = Browsable;
        }

        // ToDo: add support for custom attributes

        if (includeAll || Browsable)
        {
            dt.Columns.Add(dc);
        }
    }

    // the lst could be empty such as creating a typed table
    if (lst.Count == 0) return dt;

    if (lst[0] is IDataValuesProvider)
    {
        IDataValuesProvider dvp;
        // copy the data - let the class do the work
        foreach (T item in lst)
        {
            dvp = (IDataValuesProvider)item;
            dt.Rows.Add(dvp.GetDataValues(includeAll).ToArray());
        }
    }
    else
    {
        List<object> values;
        foreach (T item in lst)
        {
            values =  new List<object>();
            // only Browsable columns added
            for (int n = 0; n < dt.Columns.Count; n++)
            {
                 values.Add(propCol[dt.Columns[n].ColumnName].GetValue(item));
            }
            dt.Rows.Add(values.ToArray());
        }
    }   

    return dt;
}

该方法允许您指定是否Browsable应将非属性的列添加到DataTable. 如果需要,您可以完全省略它们,而不是稍后隐藏这些列。

接口证明了按顺序从集合成员获取数据值的方法(作为反射循环的替代方案):

public interface IDataValuesProvider
{
    IEnumerable<object> GetDataValues(bool includeAll);
}

... on the class:
public class StockItem : IDataValuesProvider
{
    public int Id { get; set; }
    public string ItemName {get; set;}
    [Browsable(false), DisplayName("Ignore")]
    public string propA {get; set;}
    [ReadOnly(true)]
    public string Zone { get; set; }
    public string Size {get; set;}
    [DisplayName("Nullable")]
    public int? Foo { get; set; }
    public int OnHand {get; set;}
    public string ProdCode {get; set;}
    [Browsable(false)]
    public string propB { get; set; }
    public DateTime ItemDate {get; set;}

    // IDataValuesProvider implementation
    public IEnumerable<object> GetDataValues(bool IncludeAll)
    {
        List<object> values = new List<object>();

        values.AddRange(new object[] {Id, ItemName });
        if (IncludeAll) values.Add(propA);

        values.AddRange(new object[] { Zone, Size, Foo, OnHand, ProdCode });
        if (IncludeAll) values.Add(propB);

        values.Add(ItemDate);

        return values;
    }
}

以与类中列出的顺序相同的顺序添加数据值;添加属性时请务必更新它。反射版本仍然存在,因此您可以使用任何一种方式。

最后,还有一些 commonAttribute没有相关DataColumn属性。该方法为您存储这些,ExtendedProperties以便您轻松地将它们应用于 DGV:

var dtX = someData.ToDataTable();

dgvB.SuspendLayout();
dgvB.DataSource = dtX;

// process extended props
foreach (DataColumn dc in dtX.Columns)
{
    // no need to test, the code adds them everytime
    //if (dc.ExtendedProperties.ContainsKey("DisplayName"))
    //{ 
        dgvB.Columns[dc.ColumnName].HeaderText = dc.ExtendedProperties["DisplayName"].ToString(); 
    //}
    //if (dc.ExtendedProperties.ContainsKey("Browsable"))
    //{
        dgvB.Columns[dc.ColumnName].Visible = (bool)dc.ExtendedProperties["Browsable"];
    //}
}
dgvB.ResumeLayout();

使用上面显示的类列表的结果:

在此处输入图像描述

Both OnHandandFoo显示DisplayNameand both PropAandPropB被隐藏。最重要的是,为ReadOnlyNullable属性创建的列会相应地起作用。

于 2017-01-18T19:53:30.927 回答
0

尝试这个:

     foreach (DataRow dr in list)
     {
        tempTable.Rows.Add(dr);
     }
于 2013-02-28T05:52:26.710 回答