0

I have a datagridview and a checkbox column attached to it. If the user checks a few rows and then presses a button, I would like to be able to get a certain cell value from each row where the box was ticked.

Something maybe like this:

foreach (DataGridViewRow row in dataGridView1.Rows)
{
    if (Convert.ToBoolean(row.Cells[CheckBoxColumn1.Name].Value) == true)
    {
        //...
    }
}

The problem is that the datagridview might contain up to 3000 or 4000 rows. I would like to see if there is a faster way to get the checked rows, other than to iterate through all the rows for the grid.

5
  • Why are you making your users sift through 4,000 rows? Commented Jun 8, 2016 at 16:16
  • 3000 or 4000 rows is not much. Do you have an actual performance problem? Commented Jun 8, 2016 at 16:17
  • @LarsTech It is the user's wish. And they will also be able to filter through that. Commented Jun 8, 2016 at 16:18
  • @Paparazzi I'm still in the design stage of this, I don't think it would create a bottleneck, but if there's a better way in terms of performance I would prefer it. Commented Jun 8, 2016 at 16:19
  • You should avoid premature optimization. If you are worried about performance then DataGridView and WinForms would certainly not be my pick. You have picked a very heavy weight control and you are worried about the time to iterate row. Commented Jun 8, 2016 at 16:24

4 Answers 4

2

If you don't want to iterate all rows, then use temporary list of checked rows.
Then after button was clicked use values from that List

HashSet<DataGridViewRow> _CheckedRows = new HashSet<DataGridViewRow>();

private void DataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    if (DataGridView.Columns[e.ColumnIndex].Name.Equals(CheckBoxColumn1.Name) == false)
        return;

    DataGridViewRow row = DataGridView.Rows[e.RowIndex];
    if (Convert.ToBoolean(row.Cells[CheckBoxColumn1.Name].Value) == true)
    {
        _CheckedRows.Add(row);
    }
    else
    {
        _CheckedRows.Remove(row);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Cool! I was late for a second with a similar answer.
1

You could manage your own list of checked rows. You would bind to the dataGridView1.CellClick event, and add/remove rows from the list:

var checkedRows = new List<DataGridViewRow>();

dataGridView1.CellClick += (sender, args) =>
{
    if (args.RowIndex != YOUR_CHECKBOX_COLUMN_INDEX)
    {
        return;
    }

    var cell = dataGridView1[args.ColumnIndex, args.RowIndex];

    if (cell.Value == null)
    {
        cell.Value = false;
    }

    cell.Value = !(bool)cell.Value;

    if ((bool)cell.Value)
    {
        checkedRows.Add(dataGridView1.Rows[args.RowIndex]);
    }
    else
    {
        checkedRows.Remove(dataGridView1.Rows[args.RowIndex]);
    }
};

All you have to do then is:

foreach (DataGridViewRow row in checkedRows)
{
    //...
}

Comments

0

You can use Linq like this :

var checkedRows = from DataGridViewRow r in dataGridView1.Rows
                  where Convert.ToBoolean(r.Cells[CheckBoxColumn1.Name].Value) == true
                  select r;

foreach (var row in checkedRows)
{
    //
}

1 Comment

Cleaner syntax but I doubt it is faster
0

Using CheckBoxColumn1.Name instead of CheckBoxColumn1.Index seems like a tiny bottleneck to me.

To avoid the casting to DataGridViewRow and Boolean, my suggestion is something like (not tested):

int colIndex = CheckBoxColumn1.Index; // or dataGridView1.Columns.IndexOf(CheckBoxColumn1.Name) ?
for ( int r = 0; r < dataGridView1.RowCount; r++ )
{
    if ( true.Equals( dataGridView1[colIndex, r].Value ) )
    {
        //...
    }
}

The other answers that use cell events are better because the list of checked rows will be ready when needed, but also can be a bit harder to maintain/debug depending on how you do the filtering and rest. Here is my version:

private HashSet<int> checkedRowIndexes = new HashSet<int>();

private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    if ( e.ColumnIndex == CheckBoxColumn1.Index ) 
    {
        if ( true.Equals( dataGridView1[CheckBoxColumn1.Index, e.RowIndex].Value ) )
            checkedRowIndexes.Add(e.RowIndex);
        else 
            checkedRowIndexes.Remove(e.RowIndex);
    }
}

1 Comment

@Fabio compiles for me msdn.microsoft.com/en-us/library/0syx5449. The alternatives if needed are cell.Value.Equals(true) or object.Equals( cell.Value, true )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.