如何将List转换为DataTable

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

列表:

List 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(????); } 

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

 public static DataTable ToDataTable(List 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; } 

变量声明:

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

在DataTable中添加列:

  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"); 

将DataTable转换为List:

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

在另一个DataTable中添加列:

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

将List转换为dataTable:

  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(); } 

使用CopyToDataTable()方法。 CopyToDataTable

 IEnumerable query = TempselectedFieldsTable.AsEnumerable().ToList(); // Create a table from the query. DataTable boundTable = query.CopyToDataTable(); 

试试这个:

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

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

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

以下是返回DataTable的扩展方法,可以考虑上述内容,也可以为代码提供应用它们的方法。 它还使用Interface从类对象而不是Reflection获取值。

 public static DataTable ToDataTable(this IList 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 values; foreach (T item in lst) { values = new List(); // 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 。 如果您愿意,可以完全省略它们,而不是稍后隐藏列。

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

 public interface IDataValuesProvider { IEnumerable 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 GetDataValues(bool IncludeAll) { List values = new List(); 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; } } 

按照您class级中列出的顺序添加数据值; 确保在添加属性时更新它。 reflection版仍然存在,所以你可以这样做。

最后,有一些常见的Attribute没有相关的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(); 

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

在此处输入图像描述

OnHandFoo显示DisplayName ,隐藏PropAPropB 。 最重要的是,为ReadOnlyNullable属性创建的列会相应地起作用。