2013-01-24 192 views
9

我试图改进WPF中我的树形视图的性能,当您打开一个包含6000个子项的节点时,目前需要大约13秒来显示此项。我为子集合使用了observablecollection,datatemplate绑定了约7列的TransactionViewModel类型,每个列都从视图模型中提取一段数据。WPF渲染性能降低

6000个子项的transactionviewmodels被创建并实例化,但是因为您尚未在视觉上显示任何这些子视图,所以首次展开节点时,需要13秒才能显示。如果您随后收缩并展开节点,则会立即显示零时间以显示/加载。唯一的区别是,第一次,TransactionviewModel的每个绑定依赖属性都有它的getter被XAML绑定调用,当你第二次再次展开时,没有任何事情发生变化,所以WPF并没有再次调用getters并且可能只是在第二次展开时将内存中的绑定信息保存在内存中。

因此,该控件的可视化绘图是即时的,但是第一次打开它(即使6000个transactionviewmodel对象已经完全加载到子集合中),纯粹是对行进行渲染是需要花费时间的。

有趣的是,如果我将datatemplate更改为不绑定到viewmodel对象上的ANY依赖项属性,并输出一个空格,它仍需要8秒才能加载。因此,即使没有任何数据绑定调用,树查看器也需要8秒来渲染6000行。超过5秒会给你每行5个绑定数据列,所以与基本渲染相比,这是一个很小的成本。

8s渲染6000空白行似乎对我来说很高。是否有什么主要原因可能会发生,或者从数据模板将XAML渲染到树视图中时需要注意的一些事情?我试过只使用一个空的数据模板 - 即它里面没有空格,它仍然需要7秒。

鉴于它会立即崩溃并扩展,为什么当它甚至不渲染任何XAML或调用任何数据绑定时第一次花费这么长时间?

此外,异步调用不是一个解决方案,因为我的问题不是GUI响应,而是花费时间来加载数据。用户需要比现在更快地获得数据。

非常感谢

+0

您在使用虚拟化?当你开始渲染数以千计的UI对象时,WPF的确会变慢,所以通常你只想渲染可见的项目,而不是全部渲染,并且只需在滚动时替换控件背后的DataContext。我也仔细检查确认它是导致延迟的UI渲染,而不是加载数据。 – Rachel

回答

10

它看起来像我需要在TreeView中启用虚拟化。

Optimizing Performance: Controls

默认情况下,UI虚拟化的ListView和列表框控件 启用时,他们的列表项绑定到数据。 TreeView的 虚拟化可以通过设置 VirtualizingStackPanel :: IsVirtualizing附加属性为true

+0

在我的情况下,它是VirtualizingPanel.IsVirtualizing VirtualizingStackPanel代替:: IsVirtualizing – Yogesh

+2

链接已经死了..更新https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/optimizing-performance-controls –

1

您的问题可能没有渲染,但布局 - 它有实例很多UI元素,以找到他们的大小,使其能正常大小一些UI元素(滑块),以及这需要时间。渲染可能根本不会进入。

+0

这只是树视图控件的限制吗?由于我所做的只是添加空白的子节点,并且仍然需要一段合理的时间。每行第二行开始包括小图标图像,它几乎不可用。我可以使用哪些技巧来加快速度? – NZJames

3

如果一个TreeView包含很多项目,所花费的时间来加载可能会导致在用户界面的显著延迟量启用。您可以通过将VirtualizingStackPanel.IsVirtualizing附加属性设置为true来改善加载时间。当用户使用鼠标滚轮滚动TreeView或拖动滚动条的大拇指时,用户界面的反应速度可能会很慢。通过将VirtualizingStackPanel.VirtualizationMode附加属性设置为回收,您可以在用户滚动时提高TreeView的性能。

How to: Improve the Performance of a TreeView

XAML:

<TreeView Height="200" ItemsSource="{Binding Source={StaticResource dataItems}}" x:Name="myTreeView" 
     VirtualizingStackPanel.IsVirtualizing="True" 
     VirtualizingStackPanel.VirtualizationMode="Recycling"/> 

编程:

myTreeView.SetValue(VirtualizingStackPanel.IsVirtualizingProperty, true); 
myTreeView.SetValue(VirtualizingStackPanel.VirtualizationModeProperty, VirtualizationMode.Recycling)