Вопрос

I have a datagridview control that where I need to color the rows based on a value in one of the cells in each row. I'm using the CellFormatting event like so:

Private Sub DGDisplay_CellFormatting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles dgDisplay.CellFormatting

    Dim intRowIndex As Integer = e.RowIndex 'This is zero when sorting.....
    Dim CurrentRow As DataGridViewRow = dgDisplay.Rows(intRowIndex)
    Dim strTestValue As String = CurrentRow.Cells("Status").Value

    Select Case UCase(strTestValue)
        Case "WARNING"
            CurrentRow.DefaultCellStyle.BackColor = Color.PeachPuff
        Case "ERRMESSAGE"
            CurrentRow.DefaultCellStyle.BackColor = Color.Salmon
    End Select
End Sub

This works fine when the grid loads and when I scroll it, etc. But when I click on the column headers to sort the grid, e.RowIndex is always zero and all of the rows get the formatting of the first row...

Why isn't this working when the grid sorts?

EDIT: Joakim was on the right track but the following code works correctly:

Private Sub dgDisplay_CellPainting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles dgDisplay.CellPainting

    If e.RowIndex < 0 Then
        Exit Sub
    End If

    Dim intRowIndex As Integer = e.RowIndex
    Dim CurrentRow As DataGridViewRow = dgDisplay.Rows(intRowIndex)
    Dim strTestValue As String = CurrentRow.Cells("Status").Value

    Select Case UCase(strTestValue)
        Case "WARNING"
            CurrentRow.DefaultCellStyle.BackColor = Color.PeachPuff
        Case "ERRMESSAGE"
            CurrentRow.DefaultCellStyle.BackColor = Color.Salmon
    End Select
End Sub

For some reason, e.RowIndex is set correctly here but not on the other methods. The only thing you have to worry about here is it can be -1. But when I tried to use other methods, including PrePaint, I had to deal with it always coming up zero on a sort. If I exclude the zero case, like I excluded the negative one case about, then the first row is always white!!! Madness... I'm not sure why this works, but it does. It also produces no flicker beyond what I got using the CellFormatting event.

IF ANYONE CAN EXPLAIN THE REASON WHY e.RowIndex IS BEHAVING SO WEIRD OR OFFER A BETTER WAY OF DOING THIS THEY WILL GET THE ACCEPTED ANSWER!

Это было полезно?

Решение 2

Private Sub dgDisplay_CellPainting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles dgDisplay.CellPainting

If e.RowIndex < 0 Then
    Exit Sub
End If

Dim intRowIndex As Integer = e.RowIndex
Dim CurrentRow As DataGridViewRow = dgDisplay.Rows(intRowIndex)
Dim strTestValue As String = CurrentRow.Cells("Status").Value

Select Case UCase(strTestValue)
    Case "WARNING"
        CurrentRow.DefaultCellStyle.BackColor = Color.PeachPuff
    Case "ERRMESSAGE"
        CurrentRow.DefaultCellStyle.BackColor = Color.Salmon
End Select

End Sub

Другие советы

I suggest you try RowPrePaint as it lets you alter the table before it paints anything but after it has databound it.

Your problem is that DataGridView.CellFormatting is a cell-level event, but you're using it to format the whole row.

CellFormatting is triggered for every visible cell, and for each cell you're reformatting the entire row (via CurrentRow.DefaultCellStyle), which then triggers more cell formatting events for the reformatted cells. This probably produces an event loop which is being escaped from internally, but which gives you a bogus value for RowIndex.

If you change your code to only restyle the relevant cell, your problem will disappear:

Dim currentCell As DataGridViewCell = CurrentRow(e.ColumnIndex)

Followed by:

Select Case UCase(strTestValue)
    Case "WARNING"
        currentCell.Style.BackColor = Color.PeachPuff
    Case "ERRMESSAGE"
        currentCell.Style.BackColor = Color.Salmon
End Select
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top