style triggers for alternating rows don't alwa

2019-03-02 07:07发布

问题:

There are a few questions similar to this on SO, I've read this one and another I can't find the link for, but none of them seem to have a solution that's applicable.

I have a DataGrid defined below, and it has various styles triggered on AlternationIndex being either 0 or 1. When I scroll upwards, sometimes the a given cell will flip from one colour to the other.

Do you know of any way to stop this from happening without turning off virtualization?

(I've taken the column definitions out to save space, I don't think they're important for this. All of the DataTriggers -always- work, it's just the alternation that I'm having issues with.)

<DataGrid 
        ItemsSource="{Binding Path=LogItems, Mode=OneWay}" 
        Grid.Row="1" 
        AlternationCount="2"
        Name="logDataGrid"
        VirtualizingStackPanel.IsVirtualizing="True"
        VirtualizingStackPanel.VirtualizationMode="Recycling">
        <DataGrid.Resources>
            <local:IsEntryExceptionConverter x:Key="isEntryExceptionConverter" />
            <Style TargetType="{x:Type DataGridCell}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type DataGridCell}">
                            <Border Name="DataGridCellBorder">
                                <ContentControl Content="{TemplateBinding Content}">
                                    <ContentControl.ContentTemplate>
                                        <DataTemplate>
                                            <TextBlock Background="Transparent" TextWrapping="WrapWithOverflow" TextTrimming="CharacterEllipsis" 
                                            Height="auto" Width="auto" Text="{Binding Text}"/>
                                        </DataTemplate>
                                    </ContentControl.ContentTemplate>
                                </ContentControl>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <Trigger Property="DataGridCell.IsSelected" Value="True">
                        <Setter Property="TextBlock.Foreground" Value="Blue" />
                    </Trigger>
                </Style.Triggers>
            </Style>
            <SolidColorBrush x:Key="ExceptionBrush" Color="OrangeRed" Opacity="0.5"/>
            <SolidColorBrush x:Key="ErrorBrush" Color="Red" Opacity="0.5"/>
            <SolidColorBrush x:Key="WarningBrush" Color="Orange" Opacity="0.5"/>
            <SolidColorBrush x:Key="AlternatingRowBackground0" Color="AliceBlue" Opacity="0.5" />
            <SolidColorBrush x:Key="AlternatingRowBackground1" Color="LightBlue" Opacity="0.5" />
        </DataGrid.Resources>

        <DataGrid.RowStyle>
            <Style TargetType="DataGridRow">
                <Style.Triggers>
                    <Trigger Property="AlternationIndex" Value="0">
                        <Setter Property="Background" Value="{StaticResource AlternatingRowBackground0}" />
                    </Trigger>
                    <Trigger Property="AlternationIndex" Value="1">
                        <Setter Property="Background" Value="{StaticResource AlternatingRowBackground1}" />
                    </Trigger>
                    <DataTrigger Binding="{Binding Path=Level}" Value="Warning">
                        <Setter Property="Background" Value="{StaticResource WarningBrush}" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=Message, Converter={StaticResource isEntryExceptionConverter}}" Value="True">
                        <Setter Property="Background" Value="{StaticResource ExceptionBrush}" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Path=Level}" Value="Error">
                        <Setter Property="Background" Value="{StaticResource ErrorBrush}" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.RowStyle>
    </DataGrid>

回答1:

That's the nature of virtualization. Only a set number of UI objects are actually rendered, and when you scroll you are changing the DataContext behind those objects.

So in your case, Rows are created and given a background color. When you scroll, the DataContext behind those rows change, so a data object might be in a row that was given Color A at a certain scroll position, or be in a row that was assigned color B at another scroll position.

Most of the time the alternating colors are only there to help identify what columns are in what row so it doesn't matter if they change, however if you want to maintain a consistent background color for the rows you will probably have to add something to the data object and base your background color off that property. That way when you scroll and the DataContext changes, the row color will also change.