简体   繁体   中英

Custom Sort on DataGridView with BindingSource

I'm trying to improve performance of loading a relatively large amount of data in my DataGridView and I found that the time between setting the DGV's data source to when it fully renders was really long. I isolated this to a dynamic setting of column formats in my DataBindingComplete event, which (after stepping through to find out) instead of applying the formats on a per-column basis, somehow does it on a per-cell basis (!!). This obviously jammed up the render when the number of cells was huge.

I embarked on modifying the data in-memory instead, changing the DataTable values from doubles to formatted strings via value.ToString("N") . This sped up the render significantly but I was left with several columns of strings instead of doubles that destroyed the natural sorting capability of the grid. I have searched quite a bit if custom sorting can be done on the DataGridView level, BindingSource level, or DataTable level to no avail.

Appreciate if anyone could point me in the right direction, especially if this approach is completely a bad idea and there's a better way to achieve a simple task like number formatting.

I think this article is what you are looking for? You can custom sort your BindingSource with LINQ (i guess you are using LINQ anyways?) by implementing the IComparer<T> Interface and use your custom Compare method.

For the column format you could do it like this if you need to format it, the example is a dateTime value:

dataGridView1.Columns["Column"].DefaultCellStyle.Format = "MM-dd-yyyy";

And for the custom sorting if you are taking data from a sql server you could have it order the rows it returns in the query and it will show them in that orde in the dataGridView, this is a code I use for that purpose:

string command = "SELECT * FROM [table] ORDER BY [column]";
//database connection string
string constring =[database connection string];
//open DB connection - execute query - create dataadapter - fill datatable - bind datasource to datatable
using (SqlConnection con = new SqlConnection(constring))
    {
    using (SqlCommand cmd = new SqlCommand(command, con))
        {
        cmd.CommandType = CommandType.Text;
        using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
            {
            using (DataTable dt = new DataTable())
                {
                try
                  {
                  //fill the dataGridView
                  sda.Fill(dt);
                  dataGridView1.DataSource = dt;
                  Console.WriteLine("Refreshing Complete");
                  //disable manual sorting on all columns
                  for (int i = 0; i < dataGridView1.Columns.Count; i++)
                  {
                    dataGridView1.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable;
                  }
                  //Autosize all cells
                  dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
                  dataGridView1.AutoResizeColumns();
                  }
                  catch (Exception e)
                  {
                  MessageBox.Show(e.Message);
                  }
              }
          }
       }
  }

This binds the query output to the dataGridView in the order of the returned rows, set the manual ordering of the rows to false and autosize all the columns. if you would want to refill the dataGridView you can use this:

dataGridView1.DataSource = null;
dataGridView1.Refresh();

and then run the fill again. If needed you could also change the display order of the columns and the column header names during the binding of the query output. I hope this is somewhat helpfull

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM