【发布时间】:2012-10-28 20:58:17
【问题描述】:
我们正在努力解决 wpf 中数据网格的缓慢问题。无论我们使用哪个集合——List、BindingList、ObservableCollection、自定义 ObservableCollection,响应集合更新(Clear、Add)并在屏幕上呈现时仍然非常缓慢。
我们找到的最快解决方案不是更新集合,而是更新集合中的现有对象,DataGrid 绑定到该对象。在这种情况下,网格的响应速度非常快,就像旧的 winforms 网格一样。
我们正在网格中创建 65535 行,这对于我们所有的网格来说已经足够了。在更新网格时,我们更新所需的顶部行数,并为其余部分设置可见性 = 隐藏。正如我所说,它的工作速度非常快。但是有两个问题我们无法解决:
- 滚动条,因为我们不折叠行(它很慢) - 它总是设置为 65535 行。有没有办法将滚动或网格大小限制为实际可见的行数?
另外,我注意到,将新行添加到集合中,如果它们不需要立即呈现(它们将超出可见区域)也非常快,因此我们可以将最小设置限制为 50 行(最大可见行),然后根据需要添加/删除新行。但这并不能解决滚动问题。
欢迎任何其他解决方案。 预见到启用虚拟化的建议 - 是的,我们正在使用虚拟化(对于默认启用的行和列)。
更新:
我们正在尝试显示 20 列 x 50 行的数据。如果我们用 Clear() 然后 Add() 修改源集合,渲染时间大约是 1 秒,这对我们来说根本无法接受,因为 UI 会冻结一秒。我试图将数据网格的大小调整为 0 高度,然后在后台线程中逐步设置大小,它会解冻 UI,但忽略是丑陋的,我还没有管理如何将数据网格设置回以填充父控件。似乎在代码中设置了高度之后,就没有回头路了。
与最初的帖子一样,我们发现它的替代解决方案不是修改集合。只需将网格限制为 65535 行,不要添加或删除新项目。它的运行速度非常快,但现在我们在同步滚动和排序方面遇到了问题。
我发现数据网格在 WPF 中是非常令人沮丧的控制。性能低于任何合理限制。
我们正在努力实现的是响应能力。加载数据时,它不应阻塞 UI 超过几毫秒。
XAML:没什么特别的
<DataGrid x:Name="TheGrid"
DockPanel.Dock="Top"
ItemsSource="{Binding Collection}"
EnableColumnVirtualization="True"
EnableRowVirtualization="True"
AutoGenerateColumns="False"
ColumnWidth="70"
RowHeight="20"
>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Header 1" >
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Field1, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Field1}" /></DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn >
.....等等20列
此外,数据网格不在 StackPanel 内(这使得它非常慢)。
【问题讨论】:
-
您是否在您的网格中使用
Virtualization?这只会渲染可见项目+滚动缓冲区的一些额外内容,而不是渲染整个 65535 行。也许您可以将 Grid 的 XAML 和用于清除/添加的代码发布到您的ObservableCollection? -
是的,我正在使用虚拟化。当窗口最大化时,网格大约需要 50 行 x 20 列,大约需要 1 秒来渲染它,在集合更新之后,或/并且网格变得可见。
-
您可能想阅读这篇很棒的文章:codeproject.com/Articles/34405/WPF-Data-Virtualization 所描述的方法可能不会减少渲染时间,但肯定会减少加载时间(我能够“加载”一个 20x1000半秒后的表格)。
-
@Joulukuusi 即使是半秒对我们来说也太长了。使用问题中描述的方法,UI 只需几毫秒即可更新。如果只需要更新绑定中的数据,WPF 非常快。我现在无法确定确切的时间 - 但我们加载了 5000 行而没有任何 UI 响应性松动