35

How can convert a list to a datatable

[Serializable]
public class Item
{
    public string Name { get; set; }
    public double Price { get; set; }
    public string @URL { get; set; }

    public Item(string Name, string Price, string @URL)
    {
        this.Name = Name;
        this.Price = Convert.ToDouble(Price);
        this.@URL = @URL;
    }

    public override string ToString()
    {
        return this.Name;
    }
}

I tried using:

static DataTable ConvertToDatatable(List<Item> list)
{
    DataTable dt = new DataTable();

    dt.Columns.Add("Name");
    dt.Columns.Add("Price");
    dt.Columns.Add("URL");
    foreach (var item in list)
    {
        dt.Rows.Add(item.Name, Convert.ToString(item.Price), item.URL);
    }

    return dt;
}

Now I'm getting a box show up but its empty! Help!! What can i do to make the box actually have data?

MikaAK
  • 2,334
  • 6
  • 26
  • 53
  • 1
    You say that `itemDataView` is null. What exactly is it and where is it coming from? This looks like a different issue to your conversion of a `List` to a `DataTable` – Alex Wiese Sep 29 '13 at 08:45
  • itemDataView is what was generated by the windowsform toolbox – MikaAK Sep 29 '13 at 08:49
  • Please make your issue clear. Your title says you are having problem with generating `dataTable`. But it seems that is not the issue at all. Your problem is with `itemDataView`. – Hossain Muctadir Sep 29 '13 at 09:15
  • Well i thought it was the datatable – MikaAK Sep 29 '13 at 09:25

3 Answers3

47

Just in case you have a nullable property in your class object:

private static DataTable ConvertToDatatable<T>(List<T> data)
{
    PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
    DataTable table = new DataTable();
    for (int i = 0; i < props.Count; i++)
    {
        PropertyDescriptor prop = props[i];
        if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
            table.Columns.Add(prop.Name, prop.PropertyType.GetGenericArguments()[0]); 
        else
            table.Columns.Add(prop.Name, prop.PropertyType);
    }

    object[] values = new object[props.Count];
    foreach (T item in data)
    {
        for (int i = 0; i < values.Length; i++)
        {
            values[i] = props[i].GetValue(item);
        }
        table.Rows.Add(values);
    }
    return table;
 }
MoonKnight
  • 23,214
  • 40
  • 145
  • 277
immy
  • 471
  • 4
  • 2
35

Try this

static DataTable ConvertToDatatable(List<Item> list)
{
    DataTable dt = new DataTable();

    dt.Columns.Add("Name");
    dt.Columns.Add("Price");
    dt.Columns.Add("URL");
    foreach (var item in list)
    {
        var row = dt.NewRow();

        row["Name"] = item.Name;
        row["Price"] = Convert.ToString(item.Price);
        row["URL"] = item.URL;

        dt.Rows.Add(row);
    }

    return dt;
}
Alex Wiese
  • 8,142
  • 6
  • 42
  • 71
  • 1
    I'm still getting that DataGridView is null – MikaAK Sep 29 '13 at 09:10
  • Then your issue isn't with the conversion, it's with the `DataGridView` control you added to your form. Try removing it and re-adding it and changing the name to something meaningful. – Alex Wiese Sep 29 '13 at 09:41
  • AND IT WORKS THANKYOU!! sorry but his is the code i used the datagridview remove and readd worked – MikaAK Sep 29 '13 at 09:50
2

I also had to come up with an alternate solution, as none of the options listed here worked in my case. I was using an IEnumerable and the underlying data was a IEnumerable and the properties couldn't be enumerated. This did the trick:

// remove "this" if not on C# 3.0 / .NET 3.5
public static DataTable ConvertToDataTable<T>(this IEnumerable<T> data)
{
    List<IDataRecord> list = data.Cast<IDataRecord>().ToList();

    PropertyDescriptorCollection props = null;
    DataTable table = new DataTable();
    if (list != null && list.Count > 0)
    {
        props = TypeDescriptor.GetProperties(list[0]);
        for (int i = 0; i < props.Count; i++)
        {
            PropertyDescriptor prop = props[i];
            table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
        }
    }
    if (props != null)
    {
        object[] values = new object[props.Count];
        foreach (T item in data)
        {
            for (int i = 0; i < values.Length; i++)
            {
                values[i] = props[i].GetValue(item) ?? DBNull.Value;
            }
            table.Rows.Add(values);
        }
    }
    return table;
}
Michael Brown
  • 1,585
  • 1
  • 22
  • 36