我们正在努力解决wpf中数据网格的缓慢问题。无论我们使用哪个集合--List,BindingList,ObservableCollection,自定义ObservableCollection,它在响应集合更新(清除,添加)和在屏幕上渲染时仍然非常慢。
我们发现的最快解决方案不是更新集合,而是更新DataGrid绑定的集合中的exsting对象。在这种情况下,网格响应非常快,就像旧的winforms网格一样。
我们在网格中创建了65535行,这对我们所有的网格都足够了。在更新网格时,我们会更新所需的顶行数,并为其余行设置visibility = hidden。正如我所说,它的工作速度非常快。但是有两个问题我们无法解决:
另外,我注意到,在集合中添加新行,如果它们不需要立即渲染(它们将在可见区域之外)也非常快,所以我们可以将最小集限制为50行(最大可见行),然后根据需要添加/删除新行。但这并不能解决滚动问题。
欢迎任何其他解决方案。 预见到启用虚拟化的建议 - 是的,我们正在使用虚拟化(对于默认启用的行和列)。
更新: 我们正在尝试显示20列x 50行数据。如果我们使用Clear()然后使用Add()修改源集合,则渲染时间约为1秒,这对我们来说根本不可接受,因为UI被冻结了一秒钟。我试图将datagrid的大小调整为0 Height,然后在后台线程中逐步设置大小,它解冻UI,但忽略了丑陋,我还没有管理如何设置datagrid来填充父控件。似乎在代码中设置了高度之后,就没有办法了。 与最初的帖子一样,我们发现备用解决方案不会修改集合。只需将网格限制为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列
此外,datagrid不在StackPanel内(这使得它非常慢)。
答案 0 :(得分:1)
最后,我们发现如何将滚动限制为任意数量的行而不是太多。 我们创建了自己的绑定列表,它实现了ICollection,它在ScrollView中用于获取行数。我们更改了ICollection.Count以返回在调用Measure之前设置的可见行数,然后我们将其设置回实际计数。它工作得很好,它通过滚动解决了我们所有的问题。 所以,我们有一个网格,它绑定到具有静态行数的列表,我们设置visibility =可见到我们要显示的n个第一行,其余的可见性隐藏(不是Collapesed,因为Collapsing非常慢) ,我们将滚动限制为可见行。列表中的对象可以从不同的线程更新,我们不需要调用Dispatcher,因为WPF本身就是这样做的。
答案 1 :(得分:0)
我找到了可能对您有用的网页。
第一个是关于缓存datagrid中的值: http://msdn.microsoft.com/en-us/library/system.windows.uielement.cachemode(v=vs.100).aspx
关于为datagrid实现虚拟模式的第二个: http://msdn.microsoft.com/en-us/library/15a31akc.aspx
我希望它可以帮到你
更新: 你在使用滚动视图吗?因为如果你是它将加载所有行而不是仅可见。请尝试查看此问题的答案:How to lazy-evaluate a wpf:DataGrid, retrieving data only as needed
答案 2 :(得分:0)
我知道它可能不是正确的解决方案,因为它仍然需要相同的时间。但制作多线程将解决冻结问题。然后你可以让它在背景中填充网格中的数据并逐个添加它们,或者在完成时将它们全部添加。