根据DataTable值为DataGrid行着色

时间:2016-12-21 16:39:09

标签: wpf vb.net

我从CSV文件中提取数据,在DataTable中解析数据,然后将此DataTable设置为DataGrid的ItemsSource。然后我循环DataTable来对数据进行一些验证,我想相应地为DataGrid行着色。

问题是,我无法根据DataTable行找到相应的DataGrid行。

这是我的代码:

Dim dg As New DataGrid
Dim dataTable as DataTable = ParseFile(filePath)
Dim statutList() As String = {"Saisi", "Validé", "Suspendu", "Annulé"}

dg.ItemsSource = dataTable.DefaultView

For Each row As DataRow In dataTable.Rows
    'This line is what I tried, but it always returns nothing
    Dim dgrow As DataGridRow = dg.ItemContainerGenerator.ContainerFromItem(row)
    If Not statutList.Contains(row("Statut").ToString) Then
        dgrow.Background = Brushes.Red
    End If
Next

这个问题来自于这条不起作用的行:

Dim dgrow As DataGridRow = dg.ItemContainerGenerator.ContainerFromItem(row)

解决方案:

mm8解决方案都有效。就我而言,我用过:

dg.UpdateLayout()
For Each row As DataRowView In dg.Items.OfType(Of DataRowView)
    Dim dgrow As DataGridRow = dg.ItemContainerGenerator.ContainerFromItem(row)
    If Not statutList.Contains(row("Statut").ToString) Then
        dgrow.Background = Brushes.Red
    End If
Next

1 个答案:

答案 0 :(得分:1)

正确的“WPF”方法是定义一个RowStyle,其中包含一个或多个数据触发器,当该特定行的“Statut”列返回任何特定值时,该触发器设置行的背景颜色,例如:

<DataGrid x:Name="dg">
    <DataGrid.Resources>
        <SolidColorBrush x:Key="color" Color="Red" />
    </DataGrid.Resources>
    <DataGrid.RowStyle>
        <Style TargetType="DataGridRow">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Statut}" Value="Saisi">
                    <Setter Property="Background" Value="{StaticResource color}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding Statut}" Value="Validé">
                    <Setter Property="Background" Value="{StaticResource color}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding Statut}" Value="Suspendu">
                    <Setter Property="Background" Value="{StaticResource color}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding Statut}" Value="Annulé">
                    <Setter Property="Background" Value="{StaticResource color}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGrid.RowStyle>
</DataGrid>

如果您稍微修改它,您当前的代码隐藏方法就可以正常工作:

    For Each row As DataRowView In dg.Items.OfType(Of DataRowView)
        Dim dgrow As DataGridRow = dg.ItemContainerGenerator.ContainerFromItem(row)
        If Not statutList.Contains(row("Statut").ToString) Then
            dgrow.Background = Brushes.Red
        End If
    Next

请注意,如果DataTable包含大量行而您尚未禁用UI虚拟化,则ItemContainerGenerator.ContainerFromItem方法实际上不会为可能已被虚拟化的项返回DataGridRow容器:

<DataGrid x:Name="dg" VirtualizingPanel.IsVirtualizing="False">.

如果您的DataTable包含大量行,显然禁用虚拟化可能会导致性能问题。

另请注意,一旦实际创建了容器,就需要执行代码,例如当窗口的Loaded事件发生时。

Class MainWindow
    Dim statutList() As String = {"Saisi", "Validé", "Suspendu", "Annulé"}

    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        Dim dg As New DataGrid
        Dim dataTable As DataTable = ParseFile(filePath)

        dg.ItemsSource = dataTable.DefaultView
    End Sub

    Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        For Each row As DataRowView In dg.Items.OfType(Of DataRowView)
            Dim dgrow As DataGridRow = dg.ItemContainerGenerator.ContainerFromItem(row)
            If Not statutList.Contains(row("Statut").ToString) Then
                dgrow.Background = Brushes.Red
            End If
        Next
    End Sub
    ...
End Class