c# - 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>
解决方案
推荐阅读
- javascript - 需要生成 1 - 3 之间的随机数并需要设置 3 个变量
- python - 为什么在使用 django 通用视图时出现错误?
- android - 我可以在伴生对象中共享 ViewModel 吗?
- java - File.canWrite() 重新分配后返回 false
- flutter - Flutter 在登录时显示微调器
- oracle - oracle apex 中的 URL 目标
- r - “如何获取字符串列表并根据另一列中的字符串插入新的数据框列?”
- c# - 我想在更新我的工作时更新 TextBoxes 并添加 ListView 行?
- django - NoMatchReverse 错误 ListView 到 DetailView 似乎无法传递 url 参数
- sql - 尝试使用 if/else 子句创建新列时出现 SQL 语法错误