Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filtering an DataGridView that doesn't have databinding

I have a non databound DGV (no datasource, etc; rows added manually). To filter it I'd been doing a check in a loop and setting the rows visible property appropriately. This worked well with smaller test sets, but fails utterly in performance with larger ones. 1k rows filtered at 5000/sec. 10k rows filtered at only ~250/sec. 50k at a mere 40/sec. My assumption about what's going on is that each time i change a rows visibility the DGV rebuilds a list of displayed rows turning the filtering process into an O(n^2) operation.

While even 10k rows indicates that the user is abusing the system; badly behaved users need to be accounted for so I need to do something differently. Is there a faster way to filter a large number of rows than what I'm doing now without using data binding, or do I need to fall back on clearing/recreating all the rows (for reasonable amounts of data this is significantly slower)?

//psuedocode.  runs slowly if more than a few thousand rows.
foreach (DataGridViewRow row in myDGV)
{
    row.Visible = CalculateFilter(row);
}
like image 543
Dan Is Fiddling By Firelight Avatar asked Aug 10 '09 15:08

Dan Is Fiddling By Firelight


1 Answers

I had this issue a few years ago (before I knew about databindings) and found a bug post at Microsoft, saying that this is confirmed, but the issue will propably not be fixed.

However, there are a few possibilities to solve this.

  1. Insted of adding rows to the datagridview, add rows to a datatable and bind it to the datagridview.

    DataTable table = new DataTable();
    table.Columns.Add("Name", typeof(String));
    table.Columns.Add("...", typeof(String));
    
    foreach (var element in list)
       table.Rows.Add(element.Name, element.Something);
    
    dataGridView1.DataSource = table1;
    table.DefaultView.RowFilter = "Name Like '...'";
    
  2. Create a Class that inherits from BindingList and implements IBindingList. Then bind it to your DataGridView.

  3. Set DataGridView VirtualMode to true.

Method two is more complicated, because you have to add your own logic to implement the FindCore Method.

And you should look here: http://social.msdn.microsoft.com/Forums/en-US/winformsdatacontrols/thread/68c8b93e-d273-4289-b2b0-0e9ea644623a

like image 170
Jürgen Steinblock Avatar answered Nov 15 '22 10:11

Jürgen Steinblock