首页 > 解决方案 > WPF Datagrid 单元格渲染性能问题

问题描述

我遇到了问题,我的 WPF 应用程序中有一个数据网格,它显示大约 200 个单元格(10 列,20-40 行,具体取决于窗口大小)。刷新视图(例如使用过滤器)很慢(200-400 毫秒),而我预计它会明显更快。

数据虚拟化已启用,如果我调整窗口大小以使只有 2-3 行可见,过滤器会立即刷新。这让我相信虚拟化和收集性能不是我的问题。

我运行了分析器,看起来每个单元格的渲染速度非常慢。即使删除我的自定义模板也不会将其降低到非常合理的水平。每个单元需要 5-9 毫秒来渲染,所以它加起来。

在应用程序的其他任何地方,文本块的渲染时间为 0.0015 毫秒左右。但在数据网格中,它们每个是 0.15ms,加上各种其他开销。我可以采用其他选项来提高低于 60 毫秒渲染时间的性能吗?

在此处输入图像描述

我的数据网格对象:

<DataGrid
    VirtualizingStackPanel.VirtualizationMode="Recycling"   
    VirtualizingStackPanel.IsVirtualizing="true"
    HeadersVisibility="Column" 
    BorderThickness="0 1 0 0" 
    IsReadOnly="True" 
    GridLinesVisibility="Horizontal" 
    HorizontalGridLinesBrush="#1e1e1e" 
    CanUserResizeColumns="False" 
    CanUserResizeRows="False"
    CanUserReorderColumns="False"
    EnableColumnVirtualization="True"
    EnableRowVirtualization="True"
    Margin="0 6 0 0" 
    Name="dgCombatLog"
    Foreground="#ffffff"
    Background="#252526"
    RowBackground="#252526"
    AlternatingRowBackground="#2a2a2a" 
    AlternationCount="2" 
    AutoGenerateColumns="False"
    MaxWidth="2560"
    MaxHeight="1600"
    DataGrid.RowHeight="24"
    ScrollViewer.HorizontalScrollBarVisibility="Disabled"
    ScrollViewer.VerticalScrollBarVisibility="Visible"
    RowHeaderWidth="0"
    Grid.Row="2">
    <DataGrid.Resources>
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#007acc"/>
        <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="#007acc"/>
        <Style TargetType="{x:Type DataGridColumnHeader}">
            <Setter Property="Background"  Value="#000000" />
            <Setter Property="Padding"  Value="2 2 2 2" />
        </Style>
        <Style TargetType="{x:Type DataGridCell}">
            <Setter Property="Foreground" Value="#eeeeee"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="Padding" Value="2 0 2 0"/>
            <Setter Property="Height" Value="24"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridCell}">
                        <Border Height="{TemplateBinding Height}" Padding="{TemplateBinding Padding}" Background="{TemplateBinding Background}" VerticalAlignment="Center">
                            <ContentPresenter VerticalAlignment="Center" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding ActionName}" Value="AbilityActivate" />
                        <Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=IsSelected}" Value="False" />
                    </MultiDataTrigger.Conditions>
                    <Setter Property="Background" Value="#002036" />
                </MultiDataTrigger>
                <DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType=DataGridRow}}" Value="True">
                    <Setter Property="Background" Value="#1c97ea" />
                </DataTrigger>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Self}, Path=Foreground}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </DataGrid.Resources>

    <DataGrid.Columns>
        <DataGridTextColumn Width="59" Header="@" Binding="{Binding RelativeTimestamp}" />
        <DataGridTextColumn Width="166" Header="Source" Binding="{Binding Source.Name}">
            <DataGridTextColumn.CellStyle>
                <Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Source.IsFriendly}" Value="True">
                            <Setter Property="Background" Value="#006a03"/>
                            <Setter Property="Foreground" Value="#ffffff"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Source.IsEnemy}" Value="True">
                            <Setter Property="Background" Value="#581e26"/>
                            <Setter Property="Foreground" Value="#ffffff"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </DataGridTextColumn.CellStyle>
        </DataGridTextColumn>
        <DataGridTemplateColumn Width="19" Header="A">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Image Width="14" Height="14" Source="{Binding ActionIcon}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Width="166" Header="Target" Binding="{Binding Target.Name}">
            <DataGridTextColumn.CellStyle>
                <Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Target.IsFriendly}" Value="True">
                            <Setter Property="Background" Value="#006a03"/>
                            <Setter Property="Foreground" Value="#ffffff"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Target.IsEnemy}" Value="True">
                            <Setter Property="Background" Value="#581e26"/>
                            <Setter Property="Foreground" Value="#ffffff"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </DataGridTextColumn.CellStyle>
        </DataGridTextColumn>
        <DataGridTemplateColumn Width="*" Header="Ability" SortMemberPath="AbilityDisplay" >
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <StackPanel.Resources>
                            <Style TargetType="{x:Type Image}">
                                <Setter Property="Visibility" Value="Collapsed"/>
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Path=HasAbilityIcon}" Value="True">
                                        <Setter Property="Visibility" Value="Visible"/>
                                        <Setter Property="Margin" Value="0 0 5 0"/>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </StackPanel.Resources>

                        <Image Width="18" Height="18" Source="{Binding AbilityIcon}" />
                        <TextBlock Text="{Binding AbilityDisplay}" />
                    </StackPanel>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Width="49" Header="Value" Binding="{Binding ActualValue, StringFormat={}{0:N0}}">
            <DataGridTextColumn.ElementStyle>
                <Style TargetType="TextBlock">
                    <Setter Property="HorizontalAlignment" Value="Right" />
                    <Setter Property="Foreground" Value="#daa574"/>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding ActionName}" Value="Heal">
                            <Setter Property="Foreground" Value="#32cd32"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding ActionName}" Value="Damage">
                            <Setter Property="Foreground" Value="#db001e"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Type}" Value="Spend">
                            <Setter Property="Foreground" Value="#222222"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding HasNumericValues}" Value="False">
                            <Setter Property="Foreground" Value="Transparent"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </DataGridTextColumn.ElementStyle>
        </DataGridTextColumn>
        <DataGridTextColumn Width="49" Header="Abs" Binding="{Binding AbsValue, StringFormat={}{0:N0}}">
            <DataGridTextColumn.ElementStyle>
                <Style TargetType="TextBlock">
                    <Setter Property="HorizontalAlignment" Value="Right" />
                    <Setter Property="Foreground" Value="#30cccd"/>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding AbsValue}" Value="0">
                            <Setter Property="Foreground" Value="Transparent"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </DataGridTextColumn.ElementStyle>
        </DataGridTextColumn>
        <DataGridTextColumn Width="49" Header="Over" Binding="{Binding OverValue, StringFormat={}{0:N0}}">
            <DataGridTextColumn.ElementStyle>
                <Style TargetType="TextBlock">
                    <Setter Property="HorizontalAlignment" Value="Right" />
                    <Setter Property="Foreground" Value="Transparent"/>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding ActionName}" Value="Heal">
                            <Setter Property="Foreground" Value="#8fbb8f"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </DataGridTextColumn.ElementStyle>
        </DataGridTextColumn>
        <DataGridTextColumn Width="49" Header="Threat" Binding="{Binding Threat, StringFormat={}{0:N0}}">
            <DataGridTextColumn.ElementStyle>
                <Style TargetType="TextBlock">
                    <Setter Property="HorizontalAlignment" Value="Right" />
                    <Setter Property="Foreground" Value="#daa574"/>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Threat}" Value="0">
                            <Setter Property="Foreground" Value="Transparent"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </DataGridTextColumn.ElementStyle>
        </DataGridTextColumn>
        <DataGridTextColumn Width="84" Header="Effects" />
    </DataGrid.Columns>
</DataGrid>

标签: c#wpfdatagrid

解决方案


推荐阅读