WPF DataGrid在被隐藏后刷新速度变慢

4
我正在使用一个.NET 4.0 WPF的DataGrid,它被绑定到一个ObservableCollection<T>中。这个集合每秒钟会添加和删除几次行。DataGrid位于TabControl/TabItem/Grid中。
只要我让它可见,它基本上运行得很好。如果我去到应用程序中的另一个选项卡,然后几分钟后回来,UI线程会锁定30秒钟(大约有1200行,其中大约40行在屏幕上)。所有的行数据都已经在内存中,所以没有I/O。所有绑定的属性都是简单的字符串、数字或日期,或者创建它们的逻辑非常简单;没有复杂或耗时的计算。
当有几百行以上时,选择一个新的列进行排序非常缓慢。添加新行似乎也很慢。如果我切换到另一个选项卡,然后立即切换回来,网格会快速重新出现。
调整窗口大小的性能表现良好。
滚动性能一开始很慢,但在网格完全加载后变得更好;它从来没有很好。如果不使用ScrollView.CanContentScroll="False",滚动速度太慢了,无法使用。相反,使用IsDeferredScrollingEnabled="True"会导致用户放开滚动条后渲染延迟10多秒,这仍然是一个无法接受的用户体验。
有17个DataGridTextColumns。其中几列使用自定义StringFormats,但没有复杂的内容。没有TypeConverters。
Visual Studio性能工具/分析器毫无用处。这似乎是一个相对简单/直接的设置。任何关于如何提高性能的建议都将不胜感激。
我还想知道为什么它会如此缓慢。
<DataGrid x:Name="MyGrid" AutoGenerateColumns="False" Margin="3,35,3,20" VerticalContentAlignment="Center" Width="Auto" 
                          FontSize="12" FontFamily="Consolas" ScrollViewer.CanContentScroll="False"
                          CanUserResizeRows="False" AlternationCount="2" AlternatingRowBackground="#FFE3F0FF"
                          VirtualizingStackPanel.VirtualizationMode="Recycling" IsReadOnly="True">
    <DataGrid.Columns>
        <DataGridTextColumn Header="XX" Binding="{Binding Path=XX}" />
        <DataGridTextColumn Header="YY" Binding="{Binding Path=YY, StringFormat={}{0:0.0}}">
            <DataGridTextColumn.ElementStyle>
                <Style>
                    <Setter Property="TextBlock.TextAlignment" Value="Right" />
                </Style>
            </DataGridTextColumn.ElementStyle>
        </DataGridTextColumn>
        . . .
    </DataGrid.Columns>
</DataGrid>

能否提供一个简短但完整的代码,以便重现您的问题? - Sisyphe
2个回答

4

移除 ScrollViewer.CanContentScroll = "False",这会禁用 WPF DataGrid 默认的 UI 虚拟化支持。

参考这里的回答:Physical scrolling disable UI Virtualization

从答案中可以得知:

"ScrollViewer 目前允许两种滚动模式:平滑逐像素滚动(CanContentScroll = false)或离散逐项滚动(CanContentScroll = true)。目前 WPF 仅在逐项滚动时支持 UI 虚拟化。基于像素的滚动也称为“物理滚动”,基于项的滚动也称为“逻辑滚动”."

更新

如果你想要平滑操作而你正在拖动滚动条,请将 IsDeferredScrollingEnabled 设置为 true。它将使滚动视图中的项目只在释放滚动条拇指后才呈现,而不是在拖动操作期间创建所有项目。

<DataGrid ScrollViewer.IsDeferredScrollingEnabled="True"/>

此外,来自MSDN的链接可能会对您有所帮助。

通过这个更改,点击选项卡后页面仍需要大约5秒才能刷新。不过,数据表格确实立即开始显示新数据,这是好的。不幸的是,正如我在帖子中所说的那样,它也使得滚动变得非常缓慢,无法使用。 - RickNZ
尝试在DataGrid上设置ScrollViewer.IsDeferredScrollingEnabled="True"属性。我已更新答案。看一下。 - Rohit Vats
我以前尝试过延迟滚动。是的,它确实可以让滚动条移动。然而,在你松开滚动条之后,窗口需要10秒甚至更长时间才能更新,这增加了用户的困惑和沮丧感。我想知道为什么在屏幕上更新区区40行数据(即使屏幕外还有1200多行)需要如此漫长的时间。 - RickNZ
您好,您是否找到了解决此问题的合适方法?我也遇到了同样的问题。 - Søren Engel
1
救命稻草!谢谢你! - jkl

0

我建议您调查TabControl问题,即在切换选项卡时不保留选项卡状态的问题。

TabControl有一个特定的行为-当选项卡项目未被选中时,其内容会被销毁,并且必须在再次选择选项卡项目时重新创建,这意味着必须重新创建整个DataGrid及其所有可见的DataGridCells。

只需在Google上搜索“在WPF TabControl中保留可视树”或“在WPF TabControl中保留状态”即可。


谢谢您的建议。看起来内容破坏问题只适用于在TabControl上设置ItemSource时。如果是这样,那么在我的情况下这不是问题所在,因为我没有这样做。 - RickNZ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接