1

我们正在努力解决 wpf 中数据网格的缓慢问题。不管我们使用的是哪个集合——List、BindingList、ObservableCollection、自定义ObservableCollection,在响应集合更新(Clear、Add)并在屏幕上渲染时仍然很慢。

我们找到的最快解决方案不是更新集合,而是更新集合中的现有对象,DataGrid 绑定到。在这种情况下,网格响应非常快,就像旧的 winforms 网格一样。

我们在网格中创建了 65535 行,这对于我们所有的网格来说已经足够了。在更新网格时,我们更新所需的顶部行数,并为其余部分设置可见性 = 隐藏。正如我所说,它的工作速度非常快。但是有两个问题我们无法解决:

  1. 滚动条,因为我们不折叠行(它很慢) - 它总是设置为 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 内(这使得它非常慢)。

4

3 回答 3

1

最后,我们找到了如何将滚动限制在任意数量的行上,而不是太多。我们创建了自己的绑定列表,它实现了 ICollection,在 ScrollView 中用于获取行数。我们将 ICollection.Count 更改为返回可见行的计数,这是我们在调用 Measure 之前设置的,然后我们将其设置回实际计数。它运行良好,它解决了我们所有的滚动问题。所以,我们有一个网格,它绑定到具有静态行数的列表,我们将 visibility=Visible 设置为我们想要显示的前 n 行,其余的具有可见性 Hidden(不折叠,因为折叠非常慢) ,并且我们将滚动限制为可见行。列表中的对象,可以从不同的线程更新,我们不需要调用 Dispatcher,因为 WPF 自己做。

于 2012-11-18T13:04:42.840 回答
0

我找到了可能对您有用的页面。

第一个是关于缓存数据网格中的值:http: //msdn.microsoft.com/en-us/library/system.windows.uielement.cachemode (v=vs.100).aspx

第二个关于为数据网格实现虚拟模式:http: //msdn.microsoft.com/en-us/library/15a31akc.aspx

希望对你有帮助

更新:您使用的是滚动视图吗?因为如果你是,它将加载所有行而不是仅可见。试试看这个问题的答案:How to lazy-evaluate a wpf:DataGrid, retrieving data only as needed

于 2012-11-08T16:16:43.390 回答
0

我知道这可能不是正确的解决方案,因为它仍然需要相同的时间。但是使其成为多线程将解决冻结问题。然后,您可以让它在后台将数据填充到网格中,并在运行时将它们一一添加,或者在完成后将它们全部添加。

于 2012-11-11T08:38:59.933 回答