My DataGrid has specific columns that I want to apply a background color to the cell if the value is the 1st, 2nd, or 3rd best value for that column. The datatypes are all primitives, either string, int, byte, or double.

In my old VB project that used Winforms, I would do the following: - Loop through the columns and choose only those that I wanted to colorize; - For each column I would extract all distinct values from all rows of that cell; - I would sort the values and determine the top three values, either ascending or descending, based on my preference for that individual row; - I would loop through the columns again and color the cell background color if it matched one of the top three values. I used Yellow for first, LightGreen for second, and LightBlue for first.

I have found great examples of setting up a value converter but I do not know a good way to look at all of the data for that particular column. And WPF's DataGrid doesn't seem to allow you to access individual cells, as far as I can tell.

Am I wrong? Is there a way to do this?

Here's the 8-year old VB code for a WinForms grid for reference - it does a bit more than just colorize the cells. I can't find a good way to even get started in WPF to do this.

Private Sub ColorizeRows(ByRef dgv As DataGridView) ' Colorizes the rows Dim colors() As System.Drawing.Color = {Color.Yellow, Color.Orange, Color.LightBlue}

For Each column As DataGridViewColumn In dgv.Columns
  If column.Visible = True Then

    Dim vals() As Object = GetDistinctValuesFromColumn(dgv, column.Index)

    Select Case column.ToolTipText.ToLower()
      Case "d"
        For Each row As DataGridViewRow In dgv.Rows
          row.Cells(column.Index).Style.BackColor = dgv.Columns(column.Index).DefaultCellStyle.BackColor
        Next
        Dim lowCount As Integer = (vals.GetUpperBound(0) + 1) - 3
        If lowCount < 0 Then lowCount = 0
        For j As Integer = vals.GetUpperBound(0) To lowCount Step -1
          For Each row As DataGridViewRow In dgv.Rows
            If (Not (row.Cells(column.Index).FormattedValue Is DBNull.Value)) Then
              If CStr(row.Cells(column.Index).FormattedValue) = CStr(String.Format("{0:n1}", vals(j))) Then
                row.Cells(column.Index).Style.BackColor = colors(vals.GetUpperBound(0) - j)
              End If
            End If
          Next
        Next

      Case "a"
        ' First de-colorize the row
        For Each row As DataGridViewRow In dgv.Rows
          row.Cells(column.Index).Style.BackColor = dgv.Columns(column.Index).DefaultCellStyle.BackColor
        Next
        Dim lowCount As Integer = 2
        If lowCount > vals.GetUpperBound(0) Then lowCount = vals.GetUpperBound(0)
        For j As Integer = 0 To lowCount
          For Each row As DataGridViewRow In dgv.Rows
            If (Not (row.Cells(column.Index).FormattedValue Is DBNull.Value)) Then
              If CStr(row.Cells(column.Index).FormattedValue) = CStr(String.Format("{0:n1}", vals(j))) Then
                row.Cells(column.Index).Style.BackColor = colors(j)
              End If
            End If
          Next
        Next

      Case Else
        ' do nothing

    End Select

    ' Copy the highlighting rules from the EGB box to the EGL box if we're on the dgv
    If dgv.Name = "dgvRace" Then
      For i As Integer = 0 To dgv.Rows.Count - 1
        dgv.Rows(i).Cells("effGradeLetter").Style = dgv.Rows(i).Cells("effGradeLarge").Style
      Next
    End If

    ' Update all the tooltips for each box
    Dim places() As String = {"1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th"}
    For Each row As DataGridViewRow In dgv.Rows
      ' Update tooltiptext for each row
      Dim place As Integer = FindIndexInArray(vals, row.Cells(column.Index).FormattedValue)
      If place > -1 Then
        Dim placeStr As String = IIf(column.ToolTipText.ToLower() = "d", places(vals.GetUpperBound(0) - place), places(place))
        'If column.ToolTipText.ToLower() = "d" Then place = vals.GetUpperBound(0) - place
        row.Cells(column.Index).ToolTipText = String.Format("Column Place {0}", placeStr)
        If row.Cells(column.Index).Value.GetType().ToString() = "System.Single" Or row.Cells(column.Index).Value.GetType().ToString() = "System.Int32" Then
          ' Get upper/lower difference if available
          If place > 0 Then
            Dim distFromPlaceBefore As Single = Math.Abs(CSng(vals(place)) - CSng(vals(place - 1)))
            Dim distFromFirstPlace As Single = Math.Abs(CSng(vals(place)) - CSng(vals(0)))
            row.Cells(column.Index).ToolTipText &= ControlChars.CrLf & String.Format(" - Distance from {0}: {1:n1}; Distance from 1st: {2:n1}", places(place - 1), distFromPlaceBefore, distFromFirstPlace)
          End If
          If place < vals.GetUpperBound(0) Then
            Dim distFromPlaceAfter As Single = Math.Abs(Math.Round(CSng(vals(place)) - CSng(vals(place + 1)), 1))
            Dim distFromLastPlace As Single = Math.Abs(Math.Round(CSng(vals(place)) - CSng(vals(vals.GetUpperBound(0))), 1))
            row.Cells(column.Index).ToolTipText &= ControlChars.CrLf & String.Format(" - Distance from {0}: {1:n1}; Distance from {3}: {2:n1}", places(place + 1), distFromPlaceAfter, distFromLastPlace, places(vals.GetUpperBound(0)))
          End If
        End If
      End If

    Next

  End If
Next

UPDATE: Could I somehow attach the column and the source grid so I could get the values and get what I need to make the coloring decision?

有帮助吗?

解决方案

Take a look at this article. I think that is just what you need. Pay attention to the ElementStyle with MultiBinding and CellColorConverter.

其他提示

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top