Not getting all rows when iterating through DataGr

2019-08-29 07:31发布

问题:

In a VB.NET WinForms application I have a DataGridView with a checkbox as a non-bound column in the first column. I need to add to a collection of rows each row that has its checkbox checked.

I'm using the below code to iterate through the rows and find the ones with a checked checkbox:

For Each row As DataGridViewRow In dgvEmployees.Rows

    Dim chkCell As DataGridViewCheckBoxCell = DirectCast(row.Cells(0), DataGridViewCheckBoxCell)
    If Convert.ToBoolean(chkCell.Value) = True Then
        Console.WriteLine("This should be the Emp No of the checked row: " & row.Cells(1).Value.ToString())
    End If

Next

But it is missing the last row with a checked checkbox. I.e. If I check three checkboxes, in the console output I'm seeing the "Emp No" of the first two checked rows.

Thinking it was acting like an issue with zero indexing, I also tried doing an iteration that used a counter:

For rowNum As Integer = 0 To dgvEmployees.Rows.Count - 1
    Dim currentRow As DataGridViewRow = dgvEmployees.Rows(rowNum)
    Dim chkCell As DataGridViewCheckBoxCell = DirectCast(currentRow.Cells(0), DataGridViewCheckBoxCell)

    If Convert.ToBoolean(chkCell.Value) = True Then
        Console.WriteLine("This should be the emp no of the checked row: " & currentRow.Cells(1).Value.ToString())
    End If

Next

But I get the same behavior with that code. I tried changing around the Integer = 0 and Rows.Count - 1, etc but that didn't help either.

In case it matters, the DataGridView's SelectionMode needs to be set to CellSelect.

UPDATE

There are 694 records in the table that the datagridview is being populated by.

I added a console output to get the rows.count value:

Console.WriteLine("Num rows: " & dgvEmployees.Rows.Count)

and got 695, which makes sense due to the last row in the datagridview is there to allow entry of a new row. (But I would have thought that the Count - 1 in the second iteration method would account for that.)

I also added

Console.WriteLine("Row index: " & chkcell.RowIndex)

right before the If check for a checked checkbox and, with the first, third and fifth rows checked (indexes 0, 2, 4), here's what was output:

Num rows: 695
Row index: 0
this should be the emp no of the checked row: ACS175
Row index: 1
Row index: 2
this should be the emp no of the checked row: AJAW03
Row index: 3
Row index: 4
Row index: 5
Row index: 6

There should have been a "this should be..." output after the Row index: 4 line.

回答1:

It appears that the last check box that you check is not being committed by the DataGridView because you aren't moving the focus to another cell after checking it. Try this before running your iteration code:

If dgvEmployees.IsCurrentCellDirty Then
    dgvEmployees.CommitEdit(DataGridViewDataErrorContexts.Commit)
End If