【问题标题】:WPF datagrid responsiveness- 20x50 cellsWPF 数据网格响应能力 - 20x50 单元格
【发布时间】:2012-10-28 20:58:17
【问题描述】:

我们正在努力解决 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 内(这使得它非常慢)。

【问题讨论】:

  • 您是否在您的网格中使用Virtualization?这只会渲染可见项目+滚动缓冲区的一些额外内容,而不是渲染整个 65535 行。也许您可以将 Grid 的 XAML 和用于清除/添加的代码发布到您的ObservableCollection
  • 是的,我正在使用虚拟化。当窗口最大化时,网格大约需要 50 行 x 20 列,大约需要 1 秒来渲染它,在集合更新之后,或/并且网格变得可见。
  • 您可能想阅读这篇很棒的文章:codeproject.com/Articles/34405/WPF-Data-Virtualization 所描述的方法可能不会减少渲染时间,但肯定会减少加载时间(我能够“加载”一个 20x1000半秒后的表格)。
  • @Joulukuusi 即使是半秒对我们来说也太长了。使用问题中描述的方法,UI 只需几毫秒即可更新。如果只需要更新绑定中的数据,WPF 非常快。我现在无法确定确切的时间 - 但我们加载了 5000 行而没有任何 UI 响应性松动

标签: c# wpf datagrid


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    第一个是关于缓存数据网格中的值: 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

    【讨论】:

    • 缓存在这里没有帮助。第二个链接是关于 WinForms,而不是 WPF。
    • 我更新了问题...控件不在滚动视图内
    【解决方案3】:

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

    【讨论】:

    • 是的,但是您可以在单独的线程中加载数据,因此渲染线程只需要处理渲染。
    • 数据加载为 5 毫秒,渲染 700 毫秒。这就是问题所在。
    猜你喜欢
    • 1970-01-01
    • 2018-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    相关资源
    最近更新 更多