7
votes

I have a DataGridView with a checkbox column. I'm trying to create a select/deselect all button. The code for changing the values is easy enough, but the performance is horrendous.

for (int i = 0; i < dgv.RowCount; i++)
{
    dgv.Rows[i].Cells["Selected"].Value = _selectAll;
}

_selectAll is simply a toggle bool variable. Is there a better way to do this where the performance is fast? I've tried changing the value in the underlying DataTable as well. It still takes several seconds for just a few hundred rows, but most work will be done on thousands of rows.

EDIT & SOLUTION (2011/10/4)

The main problem was in the DGV properties. Once I set,

dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells;

performance improved dramatically (per MSDN DataGridView Performance). The solutions suggested as of this edit would also improve performance slightly.

5
Try accessing the column by index instead of by name. e.g. dgv.Rows[i].Cells[1].Value = _selectAll; - Igby Largeman
Do you have grid bounded to any property or just giving it from the code behind? - Nivid Dholakia
Are you sure that is where the bottle neck is? Me thinks it is elsewhere. - Steve Wellens
@Steve Wellens : Aha! The elsewhere turns out to be the DGV properties. 'dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells;' fixed the issue (per msdn.microsoft.com/en-us/library/ha5xt0d9.aspx). Please post this as answer for future viewers. - Handprint
awesome work :) saved me today ;) - Vijay Balkawade

5 Answers

7
votes

Thanks a lot, by setting the AutoSizeColumnsMode property

dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells;

the performance is much better...

1
votes

Well, this is a common problem.
First, do you have any processing associated with the Checkbox checked change?
If so, create a bool member variable.
Initialize it to false before performing the Select All / Deselect All.
In the CheckBox checked change event -> check for the value of the bool paramter.
If it comes with false return from the event. Dont process anything.
After completing the for looping to set the select all / Deselect All, process the checked change event if necessary.
Dont forget to reset the bool parameter to true after for loop.

bool _allowProcessing = false;
//SelectAll / Deselect All
for (int i = 0; i < dgv.RowCount; i++)
{
   dgv.Rows[i].Cells[4].Value = _selectAll;
}
_allowProcessing = true;
// Do some processing if required

// Checked change event
public void CheckBox_CheckedChange(object sender, eventArgs e)
{
  if(!_allowProcessing)
    return;

  // Do Processing
}
0
votes

Not sure if you'll get a performance boost or not, but something else you can try:

for (int i = 0; i < dgv.RowCount; i++)
{
    dgv["Selected", i].Value = _selectAll;
}
0
votes

Instead of giving the gridview column name, u can specify which column it belongs to.This will work faster. Hope it helps.

for (int i = 0; i < dgv.RowCount; i++)
{
   dgv.Rows[i].Cells[4].Value = _selectAll;
}
0
votes

I show another way to improve this problem.
Accessing datagridview directly like dgv.Rows[i].Cells["Selected"].Value makes datagridview slowly.

So, changing datasource and refreshing datagridview makes match better performance if your datagridview has datasource and the datasouce has checked status.

foreach (var item in yourDataSource)
{
    item.Checked = _selectAll;
}
dgv.Invalidate();