Adding object to DataTable and create a dynamic GridView

11,711

Solution 1

I believe that you have make a mistake on the loop

// remove that line
// for (int i = 0; i < products.Count; i++)
int i = 0;
{    
    foreach (Product item in products)
    {    
        drow = dt.NewRow();
        dt.Rows.Add(drow);
        dt.Rows[i][col1] = item.ProductName.ToString();// i.ToString();
        dt.Rows[i][col2] = item.ProductDescription.ToString();
        dt.Rows[i][col3] = String.Format("{0:C}", item.Price);
        dt.Rows[i][col4] = String.Format("{0:.00}", item.Price);
        // and here move to next
        i++;
    }    
}

Solution 2

Though the above answer is right.

But a better way would be to write extension method which converts the collection to DataTable and we can use it anywhere in the application, i have one in my project which is used to Convert List<T> to DataTable.

Here it goes:

public static class ListExtensions
{
   public static DataTable ToDataTable<T>(this List<T> iList)
   {
    DataTable dataTable = new DataTable();
    PropertyDescriptorCollection propertyDescriptorCollection =
        TypeDescriptor.GetProperties(typeof(T));
    for (int i = 0; i < propertyDescriptorCollection.Count; i++)
    {
        PropertyDescriptor propertyDescriptor = propertyDescriptorCollection[i];
        Type type = propertyDescriptor.PropertyType;

        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
            type = Nullable.GetUnderlyingType(type);


        dataTable.Columns.Add(propertyDescriptor.Name, type);
    }
    object[] values = new object[propertyDescriptorCollection.Count];
    foreach (T iListItem in iList)
    {
        for (int i = 0; i < values.Length; i++)
        {
            values[i] = propertyDescriptorCollection[i].GetValue(iListItem);
        }
        dataTable.Rows.Add(values);
    }
    return dataTable;
  }
}

and just use it on any List<T> this way:

List<Product> products = new List<Product>();
DataTable dtProducts = products.ToDataTable();
Share:
11,711
Kev
Author by

Kev

Updated on July 22, 2022

Comments

  • Kev
    Kev almost 2 years

    I have a lot of this working and have created a dropdown and a treeview using this technique. An ajax call to create controls on the fly and return them to the page fully constructed and configured using jqueryajax and C#. But Im stuck on creating a datatable from my class object. The control obviously returns a double looped gridView, I just want it to write out a view of the returned data, eventually with all the goodness of gridView CRUD Ops. Its something simple Im doing wrong can you help?

    Here is my C# code for creating a GridView

    [WebMethod]
            public static AjaxReturnObject GetProductsByCategoryID(string CategoryID)
            {
                AjaxReturnObject o = new AjaxReturnObject();
                int catID = Convert.ToInt32(CategoryID);
                Product.ProductCollection products = new Product().GetProductsByCategoryID(catID);
                if (products.Count == 0)
                {
                    o.Message = "There was no data returned";
                    o.Status = 999;
    
                    return o;
                }
                else
                {
                    // build a new GridView (or List View) for the UI and populate it with data.
                    // 1: Initialize a object of type DataTable.
                    DataTable dt = new DataTable();
    
                    //2: Initialize a object of type DataRow
                    DataRow drow;
    
                    //3: Initialize enough objects of type DataColumns
                    DataColumn col1 = new DataColumn("Product Name", typeof(string));
                    DataColumn col2 = new DataColumn("Product Description", typeof(string));
                    DataColumn col3 = new DataColumn("Price", typeof(string));
                    DataColumn col4 = new DataColumn("Col4", typeof(string));
    
                    //4: Adding DataColumns to DataTable dt
                    dt.Columns.Add(col1);
                    dt.Columns.Add(col2);
                    dt.Columns.Add(col3);
                    dt.Columns.Add(col4);
    
                    //5: Adding values in DataColumns       
                    for (int i = 0; i < products.Count; i++)
                    {
    
                        foreach (Product item in products)
                        {
    
                            drow = dt.NewRow();
                            dt.Rows.Add(drow);
                            dt.Rows[i][col1] = item.ProductName.ToString();// i.ToString();
                            dt.Rows[i][col2] = item.ProductDescription.ToString();
                            dt.Rows[i][col3] = String.Format("{0:C}", item.Price);
                            dt.Rows[i][col4] = String.Format("{0:.00}", item.Price);
                        }
    
                    }
    
    
                    GridView GridView1 = new GridView();
                    GridView1.DataSource = dt;
                    GridView1.DataBind();
    
    
                    // Render the new control and return it to the Ajax Return Object
                    StringWriter tw = new StringWriter();
                    Html32TextWriter writer = new Html32TextWriter(tw);
                    GridView1.RenderControl(writer);
                    writer.Close();
                    o.Object = tw.ToString();
    
    
                    o.Message = "Result Data Message";
                    o.Status = 1;
    
                    return o;
                }
            }
        }
    
  • Kev
    Kev over 11 years
    Aristos, it works a treat. Thank you so much. This technique seems to be very fast to return fully constructed controls on the fly, I hope I can complete a gridview fully. Do you see any technical issues or best practice advice for this use?
  • Kev
    Kev over 11 years
    Hi Gaurav thanks for your reply - Product item = products[i]; produces Null Reference Ex for item at item.ProductName etc...
  • Gaurav Rajput
    Gaurav Rajput over 11 years
    @Kev: It must work as working here correctly because item is initialized by ith item of products collection. Anyway approach suggested by Aristos is the another approach to serve your purpose,glad to find that your problem is resolved. I have a query regarding optimization of your code that why you are converting from collection to DataTable then binding this dt object to gridview, i mean what if you bind direct collection to gridview. If formatting is required then you can change structure of Product class.
  • Kev
    Kev over 11 years
    Yes I was binding collection directly with good results, but needed to format the columns, this is why DataTable needed -Thanks