WPF 数据网格性能
Posted
技术标签:
【中文标题】WPF 数据网格性能【英文标题】:WPF Datagrid Performance 【发布时间】:2010-10-16 09:51:23 【问题描述】:我正在使用 WPF Toolkit 数据网格,目前它的滚动速度非常慢。网格有 84 列和 805 行。 (包括 3 个固定列和标题是固定的。)水平和垂直滚动都非常慢。虚拟化已打开,我已在 xaml 中显式启用列虚拟化和行虚拟化。有什么需要注意的会真正影响性能,例如绑定方法,或者每个单元格模板中的 xaml 是什么?
需要注意的一点是,我在创建数据网格时动态添加列。那会影响什么吗? (我还同时动态创建单元格模板,以便我的绑定设置正确。)
以下是生成的大多数单元格的模板代码。基本上对于我需要动态添加的列(其中大部分),我遍历我的列表并使用 AddColumn 方法添加列,另外我动态构建模板以便绑定语句正确索引集合中的正确项目对于该列。模板不太复杂,只有两个 TextBlock,但我确实在每个上绑定了四个不同的属性。通过将绑定更改为 OneWay,我似乎能够挤出更多性能:
private void AddColumn(string s, int index)
DataGridTemplateColumn column = new DataGridTemplateColumn();
column.Header = s;
//Set template for inner cell's two rectangles
column.CellTemplate = CreateFactViewModelTemplate(index);
//Set Style for header, ie rotate 90 degrees
column.HeaderStyle = (Style)dgMatrix.Resources["HeaderRotateStyle"];
column.Width = DataGridLength.Auto;
dgMatrix.Columns.Add(column);
//this method builds the template for each column in order to properly bind the rectangles to their color
private static DataTemplate CreateFactViewModelTemplate(int index)
string xamlTemplateFormat =
@"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column=""0"" MinHeight=""10"" MinWidth=""10"" HorizontalAlignment=""Stretch"" Padding=""3 1 3 1"" TextAlignment=""Center"" Foreground=""Binding Path=FactViewModels[~Index~].LeftForeColor,Mode=OneWay"" Background=""Binding Path=FactViewModels[~Index~].LeftColor,Mode=OneWay"" Text=""Binding Path=FactViewModels[~Index~].LeftScore,Mode=OneWay"" />
<TextBlock Grid.Column=""1"" MinHeight=""10"" MinWidth=""10"" HorizontalAlignment=""Stretch"" Padding=""3 1 3 1"" TextAlignment=""Center"" Foreground=""Binding Path=FactViewModels[~Index~].RightForeColor,Mode=OneWay"" Background=""Binding Path=FactViewModels[~Index~].RightColor,Mode=OneWay"" Text=""Binding Path=FactViewModels[~Index~].RightScore,Mode=OneWay"" />
</Grid>
</DataTemplate>";
string xamlTemplate = xamlTemplateFormat.Replace("~Index~", index.ToString());
return (DataTemplate)XamlReader.Parse(xamlTemplate);
【问题讨论】:
是的,Microsoft Excel 甚至比最快的商业 WPF 数据网格控件快 100 倍。数据网格确实突出了 WPF 的弱点。 15 年前的 Delphi 数据网格在 15 年前的硬件上运行得更快。 【参考方案1】:由于我看不到您的源代码,因此很难为您提供帮助。特别是因为 WPF 应用程序的性能受到很多因素的影响。有关注意事项的一些提示,请参阅Optimizing WPF Application Performance。是的 - 每个单元格中使用什么 xaml 非常重要。因为通常性能问题归结为“元素太多”。你知道我认为一个 TextBox 是 30 个单独的元素吗?我建议您使用Performance Profiling Tools for WPF 来了解有关您的具体问题的更多信息。尽量减少使用的元素数量(例如,在适当的情况下从 TextBox 切换到 TextBlock)。
此外,您还必须检查在您试用该应用程序的任何 PC 上是否存在性能问题。也许您正在使用的 PC 迫使 WPF 进入基于软件的渲染。或者您是否在使用任何 BitmapEffects?
编辑: 查看您的代码,我建议您更改
column.Width = DataGridLength.Auto;
到一个合理的固定宽度,因为数据网格不必在每次发生变化(如添加行,甚至滚动)时动态地重新计算宽度。
【讨论】:
使用.net 4.0 DataGrid(以前的工具包之一),我有同样该死的问题,我只使用DataGridTextBoxColumns。我有更少的行(20,这意味着行虚拟化在我的情况下是无用的),但是 100 列(这里虚拟化有很大的不同,但是每次水平滚动时仍然需要大约 2 秒来显示网格和刷新 1 秒.. .)。将 bindingMode 设置为 oneWay 对我来说根本没有任何区别:(。仍在试图找出一种让事情变得更快的方法,但据我所知,这是整个 DG 创建细胞的速度非常慢。 .【参考方案2】:关于 DataGrid 性能问题的一般提示:我遇到了 DataGrid 的问题,在该问题中,在调整窗口大小、列排序等之后需要几秒钟才能刷新,并且在执行此操作时锁定了窗口 UI(1000 行, 5 列)。
这归结为 WPF 大小计算的问题(错误?)。我将它放在 RowDefinition Height="Auto" 的网格中,这导致渲染系统在运行时尝试通过测量每一列和每一行的大小来重新计算 DataGrid 的大小,大概是通过填充整个网格(据我了解)。它应该以某种方式智能地处理这个问题,但在这种情况下它不是。
快速检查这是否是相关问题是在测试期间将 DataGrid 的 Height 和 Width 属性设置为固定大小,然后再次尝试运行。如果您的性能得到恢复,则可以使用以下选项进行永久性修复:
将包含元素的大小更改为相对 (*) 或 固定值 将 DataGrid 的 MaxHeight 和 MaxWidth 设置为更大的固定值 比正常使用时更容易 尝试使用不同大小调整策略(Grid、DockPanel 等)的其他容器类型【讨论】:
将 DataGrid.Height 设置为固定值解决了我的问题。谢谢! 设置 DataGrid.MaxHeight 也有帮助。【参考方案3】:在我的一个项目中,以下网格样式设置导致了主要的性能问题:
<Style TargetType='x:Type controls:DataGrid'>
<Setter Property='ScrollViewer.CanContentScroll' Value='False' />
...
当我删除 ScrollViewer.CanContentScroll 设置后,性能问题就消失了。
【讨论】:
你是我的英雄。我搜索了这个问题很长时间。这就是解决方案。用户界面立即响应仅删除此行... 您可以将其添加到样式中(如答案所述)。或者您可以将其添加到您的数据网格中:您是否安装了任何类型的平板电脑(通过 USB 或平板电脑)?
我在使用平板电脑时在 WPF 数据网格中发现了一个性能错误。我发布了一个视频,得到了 MS here in this thread
的认可干杯, 乔恩
【讨论】:
不幸的是 WPF 的 DataGrid 速度非常慢,没有任何与平板电脑相关的错误。 我在一个关键任务实时应用程序中使用它(大概有 20-30 个实例,每个网格有 2K-3K 条记录),它对我们来说很快。 好吧,问题是有很多 WinForms/native 解决方案可以毫不费力地处理 100K 行/20 列。 DataGrid 就没那么幸运了。 是的...从未尝试过 100K 行...但我的行在上述规格中有图标、渐变等。只是一个参考点...【参考方案5】:我有一个案例,我的底层对象只有 setter 的属性。通过在集合中实现 ITypedList 并通过单个对象上的 TypeDescriptionProvider/ICustomTypeDescriptor 可以访问相同的属性。删除属性或添加 getter 解决了性能问题。
【讨论】:
【参考方案6】:在这种情况下,我建议的一件事是查看您如何应用样式以及每个单元格上的样式。 如果它具有复杂的视觉树,则应用的样式确实会降低性能。
您也可以在最新的 WPF Datagrid 上尝试延迟滚动选项。
【讨论】:
以上是关于WPF 数据网格性能的主要内容,如果未能解决你的问题,请参考以下文章