WPF DataGrid - 如果该列的绑定数据中的第1,第2或第3个最佳值,则为单元格着色

时间:2013-06-03 05:44:59

标签: c# wpf wpfdatagrid colorize

我的DataGrid有特定的列,如果该值是该列的第1,第2或第3个最佳值,我想将背景颜色应用于单元格。数据类型都是基元,可以是字符串,整数,字节或双精度。

在我使用Winforms的旧VB项目中,我会执行以下操作: - 循环遍历列并仅选择我想要着色的那些; - 对于每一列,我将从该单元格的所有行中提取所有不同的值; - 我会根据我对该行的偏好,对值进行排序并确定前三个值(升序或降序); - 如果匹配前三个值中的一个,我会再次遍历列并为单元格背景颜色着色。我首先使用Yellow,第二次使用LightGreen,第一次使用LightBlue。

我找到了设置值转换器的很好的例子,但我不知道查看该特定列的所有数据的好方法。据我所知,WPF的DataGrid似乎不允许您访问单个单元格。

我错了吗?有没有办法做到这一点?

这是用于WinForms网格的8年旧VB代码供参考 - 它不仅仅是对单元格进行着色。我找不到一个好的方法来开始使用WPF来实现这一目标。

Private Sub ColorizeRows(ByRef dgv As DataGridView)     '对行进行着色     昏暗的颜色()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

更新:我可以以某种方式附加列和源网格,以便我可以获取值并获得我做出着色决定所需的内容吗?

2 个答案:

答案 0 :(得分:1)

看看这个article。我认为这正是你所需要的。注意使用MultiBinding和CellColorConverter的ElementStyle。

答案 1 :(得分:0)