2016-03-01 96 views
0

我需要让我的DataGrid中的单元格反映有条件的规则......我已经得到了很多,并且已经花费了太多时间在此我希望有人可以帮助我?所以,这是我的网格目前的样子时运行:WPF DataGrid - 在单个单元格上条件格式化的触发器

enter image description here

在这里你可以看到(忽略成果 & 标准列),有三组两列同在这里关注。我目前将条件规则应用于XPercVerified列,但最终我希望EF [X]列显示基于相应PercVerified列中的值的背景更改。还有一点需要说明的是,可以有任意数量的这些双列组合......

但是我现在的问题是我似乎只能应用规则来有条件地格式化整个行。在上面的屏幕截图中,您可以看到1PercVerified列在第一行有1个。这会使整行变为绿色。代码如下:

Private Sub dgUnitMatrix_AutoGeneratingColumn(sender As Object, e As DataGridAutoGeneratingColumnEventArgs) Handles dgUnitMatrix.AutoGeneratingColumn 

    If (e.Column.Header.ToString().Contains("PercVerified")) Then 

     e.Column.CellStyle = TryCast(Application.Current.FindResource("PercVerified"), Style) 

    End If 

End Sub 

在这里,我们调用AutoGeneratingColumn事件,当我们有一个列,它是PercVerified,调用应用资源风格:

<Application x:Class="Application" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    StartupUri="MainWindow.xaml" 
ShutdownMode="OnMainWindowClose"> 

    <Application.Resources> 

     <Style x:Key="PercVerified" TargetType="{x:Type DataGridCell}" > 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding 1PercVerified}" Value="0"> 
        <Setter Property="Background" Value="DarkRed"></Setter> 
        <Setter Property="Foreground" Value="White"></Setter> 
        <Setter Property="Margin" Value="-2.0"></Setter> 
       </DataTrigger> 
       <DataTrigger Binding="{Binding 1PercVerified}" Value="1"> 
        <Setter Property="Background" Value="DarkGreen"></Setter> 
        <Setter Property="Foreground" Value="White"></Setter> 
        <Setter Property="Margin" Value="-2.0"></Setter> 
       </DataTrigger> 
      </Style.Triggers> 
     </Style> 

    </Application.Resources> 
</Application> 

其中存在Application.XAML文件。 我似乎有另一个问题是,即使我可以得到上面的工作只是单元格(而不是行) - 我似乎只能在我的条件下确定(即限制值必须等于 - 我不能做整数大于或小于?)......这是真的吗?

我已经开始寻找更远的地方,因为我感觉这种造型不适合我想要的工作......所以,IValueConverters已经出现了几次,但我似乎不能够得到这个工作。是否值得我花时间研究这些只是为了发现它是另一个死胡同?

我可以提供任何额外的信息,任何人都可能需要...我渴望得到这个排序,因为我已经浪费了太多的时间在WPF中的东西,只是在WinForms中很容易!

编辑

继从J.H.的出色答卷我已将它作为对象值传递给DataRowView(而不是示例Class Object),以适应它。

在转换器中,我们正在创建变量dc。这样做的条件格式比较时,而不是

' Get the cells DataContext as our data class ' 
    Dim dc As DataRowView 
    dc = TryCast(cell.DataContext, DataRowView) 
    If IsNothing(dc) Then Exit Function 

    ' Get the column number of the columnName that matches the Path 
    Dim ColNo As Integer 
    Dim idx As Integer = 0 
    For Each column As DataColumn In dc.DataView.Table.Columns 
     If column.ColumnName = path Then 
      ColNo = idx 
     End If 
     idx = idx + 1 
    Next 

然后:代码,整个区块已被更改为

Dim pv = dc.GetType().GetProperty(path).GetValue(dc) 

我们使用

Dim pv As String = dc.Row.Item(ColNo).ToString() 

除了少数其他由于差异的变化,这是一种享受!

回答

1

你可以用IValueConverter来做到这一点。您需要将DataGridCell传递给转换器。从单元格中,您可以获取datacontext和单元格的绑定。一旦你有了这些,一些反射可以让你得到PercVerifiedX字段的价值。您可以检测EFX字段,然后获取与之配套的相应PercVerifiedX字段。

以下是一些代码,请注意我的属性名称与您的属性不太相同(无法使用数字开始属性),因此您可能必须调整一些代码。另外,我可以使用数字,但为DataTrigger.Value选择字符串只是为了表明它不是PercVerified值,而是转换器的返回值。 而且,我混合了一点 - 红色为0 percs,绿色为1-3 percs,紫色为4+ perc。查看xaml和转换器的代码。

XAML

<Window x:Class="MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:WpfApplication16" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <local:PercVerifiedConverter x:Key="PercVerifiedConverter" /> 
     <Style x:Key="PercVerified" TargetType="{x:Type DataGridCell}" > 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource PercVerifiedConverter}}" Value="Red"> 
        <Setter Property="Background" Value="DarkRed"></Setter> 
        <Setter Property="Foreground" Value="White"></Setter> 
        <Setter Property="Margin" Value="-2.0"></Setter> 
       </DataTrigger> 
       <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource PercVerifiedConverter}}" Value="Green"> 
        <Setter Property="Background" Value="DarkGreen"></Setter> 
        <Setter Property="Foreground" Value="White"></Setter> 
        <Setter Property="Margin" Value="-2.0"></Setter> 
       </DataTrigger> 
       <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource PercVerifiedConverter}}" Value="Purple"> 
        <Setter Property="Background" Value="Purple"></Setter> 
        <Setter Property="Foreground" Value="Yellow"></Setter> 
        <Setter Property="Margin" Value="-2.0"></Setter> 
       </DataTrigger> 
      </Style.Triggers> 
     </Style> 
    </Window.Resources> 
    <DataGrid ItemsSource="{Binding Data}" AutoGeneratingColumn="DataGrid_AutoGeneratingColumn" /> 
</Window> 

.VB(什么与评论的一个PITA得到的颜色编码中右)

Imports System.Globalization 

Class MainWindow 
    Public Sub New() 
     ' This call is required by the designer. ' 
     InitializeComponent() 

     Dim vm As New VM 
     vm.Data = New List(Of MyData) From { 
       New MyData() With {.Outcome = "Outcome 1", .Criterion = "1.1", .PercVerified1 = 1, .EF1 = "EP, ECH", .PercVerified3 = 0, .EF3 = "", .PercVerified4 = 0, .EF4 = "EWT"}, 
       New MyData() With {.Outcome = "", .Criterion = "1.2", .PercVerified1 = 0, .EF1 = "", .PercVerified3 = 1, .EF3 = "O, EP", .PercVerified4 = 0, .EF4 = ""}, 
       New MyData() With {.Outcome = "", .Criterion = "1.3", .PercVerified1 = 0, .EF1 = "", .PercVerified3 = 0, .EF3 = "O, EP", .PercVerified4 = 4, .EF4 = ""} 
      } 
     Me.DataContext = vm 
    End Sub 

    Private Sub DataGrid_AutoGeneratingColumn(sender As Object, e As DataGridAutoGeneratingColumnEventArgs) 
     If (e.Column.Header.ToString().Contains("PercVerified") Or e.Column.Header.ToString().Contains("EF")) Then 
      e.Column.CellStyle = TryCast(Me.FindResource("PercVerified"), Style) 
     End If 
    End Sub 
End Class 

Public Class MyData 
    Public Property Outcome As String 
    Public Property Criterion As String 
    Public Property PercVerified1 As String 
    Public Property EF1 As String 
    Public Property PercVerified3 As String 
    Public Property EF3 As String 
    Public Property PercVerified4 As String 
    Public Property EF4 As String 
End Class 

Public Class VM 
    Public Property Data As List(Of MyData) 
End Class 

Public Class PercVerifiedConverter 
    Implements IValueConverter 

    Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert 
     Convert = Nothing 
     Dim cell As DataGridCell 
     Dim dc As MyData 

     ' Get the DataGridCell passed in ' 
     cell = TryCast(value, DataGridCell) 
     If IsNothing(cell) Then Exit Function 

     ' Get the cells DataContext as our data class ' 
     dc = TryCast(cell.DataContext, MyData) 
     If IsNothing(dc) Then Exit Function 

     ' Get the cells column - need it for the binding ' 
     Dim tc As DataGridTextColumn ' Assuming your cells are DataGridTextColumns ' 
     tc = TryCast(cell.Column, DataGridTextColumn) 
     If IsNothing(tc) Then Exit Function 

     ' Get the columns binding ' 
     Dim b As Binding 
     b = TryCast(tc.Binding, System.Windows.Data.Binding) 
     If IsNothing(b) Then Exit Function 

     ' Get the path off the binding ' 
     Dim path As String 
     path = b.Path.Path ' Name of the property this column is bound to - PercVerified1, EF1, etc... ' 

     ' If one of the "EF" properties, convert path to the appropriate "PercVerified" path ' 
     If path.Contains("EF") Then 
      Dim pvNum = path.Replace("EF", String.Empty) ' EF1 becomes 1 ' 
      path = "PercVerified" + pvNum ' path is now PercVerified1 ' 
     End If 
     If path.Contains("PercVerified") Then 
      Dim pv = dc.GetType().GetProperty(path).GetValue(dc) 
      If pv = 0 Then 
       Convert = "Red" 
      ElseIf pv >= 1 And pv <= 3 Then 
       Convert = "Green" 
      ElseIf pv >= 4 Then 
       Convert = "Purple" 
      End If 
     End If 
    End Function 

    Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack 
     Throw New NotImplementedException() 
    End Function 
End Class 

而且,截图:

enter image description here

+0

感谢这一切,它完全让我朝着我所寻找的方向前进。我想我现在已经解决了这个问题。我做了一些工作来做这件事,虽然因为传递给你的转换器的'值'是MyData对象的实例(使用你使用的属性)..对于我,我得到了(我认为??)一个具有列和行的DataRow ..所以我需要在那里做点什么。我会更新! – CJH

+0

纠正 - 我的DataContext的值实际上是一个DataRowView。我希望我能做到这一点,复制获得PV价值。 – CJH

+0

管理得到这个自定义,使用DataRowView作为值而不是MyData对象传递。我将在原始问题的编辑中发布我的更改。非常感谢agani J.H. – CJH

相关问题