WPF 渲染速度慢
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14500543/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF rendering slow performance
提问by NZJames
I'm trying to improve the performance of my treeview in WPF, when you open a node with 6000 children, it takes about 13 seconds currently to display this. I am using an observablecollection for the child collection, with a datatemplate bound to the TransactionViewModel type which has about 7 columns, each pulling in a piece of data from the view model.
我正在尝试提高 WPF 中树视图的性能,当您打开一个具有 6000 个子节点的节点时,当前显示该节点大约需要 13 秒。我正在为子集合使用一个 observablecollection,一个数据模板绑定到 TransactionViewModel 类型,它有大约 7 列,每列从视图模型中提取一段数据。
The transactionviewmodels for the 6000 children are created and instantiated, but as you haven't displayed any of them visually yet, the first time you expand the node, it takes the 13 seconds to display. if you then contract and expand the node, it displays instantly with zero time to display/load. The only difference I can see is that the first time each of the bound dependency properties of the TransactionviewModel has it's getter called by the XAML binding, and when you re-expand the second time, none of this happens as nothing has changed so WPF doesnt call the getters again and presumably just holds the bound information in memory for when you expand it the second time.
6000 个子节点的事务视图模型已创建并实例化,但由于您尚未直观地显示它们中的任何一个,因此第一次展开节点时,显示需要 13 秒。如果您然后收缩并展开节点,它会立即显示,显示/加载时间为零。我能看到的唯一区别是,TransactionviewModel 的每个绑定依赖属性第一次被 XAML 绑定调用时,当您第二次重新扩展时,这一切都没有发生,因为没有任何变化,所以 WPF 不会再次调用 getter,大概只是将绑定信息保存在内存中,以便在您第二次扩展它时使用。
So the visual drawing of the control is instant, but the first time you open it (even though the 6000 transactionviewmodel objects are already fully loaded into the child collection), purely the rendering of the rows is what's taking the time.
所以控件的可视化绘制是即时的,但是在您第一次打开它时(即使 6000 个事务视图模型对象已经完全加载到子集合中),纯粹是行的渲染需要时间。
Interestingly if I alter the datatemplate to not bind to ANY dependency properties on the viewmodel object and just output a blank grid, it still takes 8 seconds to load. So even without any data binding calls, the tree viewer takes 8 seconds to render 6000 rows. 5 seconds extra then gives you about 5 bound data columns per row, so that is a small cost compared to the basic rendering.
有趣的是,如果我将数据模板更改为不绑定到视图模型对象上的任何依赖项属性,而只是输出一个空白网格,则加载仍然需要 8 秒。因此,即使没有任何数据绑定调用,树查看器也需要 8 秒来呈现 6000 行。额外的 5 秒为您提供每行大约 5 个绑定数据列,因此与基本渲染相比,这是一个很小的成本。
8s to render 6000 blank rows seems very high to me. Are there any major reasons why this might be happening or things to be aware of in rendering XAML into a treeview from data templates? Ive tried using just an empty datatemplate - ie not even a blank grid inside it and it still takes 7 seconds.
8s 渲染 6000 个空白行对我来说似乎非常高。是否有任何主要原因可能会发生这种情况,或者在将 XAML 从数据模板渲染到树视图时需要注意什么?我试过只使用一个空的数据模板 - 即里面甚至没有一个空白的网格,它仍然需要 7 秒。
Given that it then collapses and expands instantly, why is it taking so long the first time when it isn't even rendering any XAML or calling any data bindings?
鉴于它随后会立即折叠和展开,为什么在第一次它甚至不呈现任何 XAML 或调用任何数据绑定时要花这么长时间?
Also asynch calls are not a solution as my problem is not GUI responsitivy but time taken to load data. The user needs to have the data quicker than they are getting it right now.
异步调用也不是解决方案,因为我的问题不是 GUI 响应,而是加载数据所需的时间。用户需要比现在更快地获得数据。
Many thanks
非常感谢
回答by jschroedl
It looks to me like you need to enable virtualization in the TreeView.
在我看来,您需要在 TreeView 中启用虚拟化。
From Optimizing Performance: Controls:
从优化性能:控制:
By default, UI virtualization is enabled for the ListView and ListBox controls when their list items are bound to data. TreeView virtualization can be enabled by setting the VirtualizingStackPanel::IsVirtualizing attached property to true
默认情况下,当 ListView 和 ListBox 控件的列表项绑定到数据时,会为它们启用 UI 虚拟化。可以通过将 VirtualizingStackPanel::IsVirtualizing 附加属性设置为 true 来启用 TreeView 虚拟化
回答by Ash
If a TreeView contains many items, the amount of time it takes to load may cause a significant delay in the user interface. You can improve the load time by setting the VirtualizingStackPanel.IsVirtualizing attached property to true. The UI might also be slow to react when a user scrolls the TreeView by using the mouse wheel or dragging the thumb of a scrollbar. You can improve the performance of the TreeView when the user scrolls by setting the VirtualizingStackPanel.VirtualizationMode attached property to Recycling.
如果 TreeView 包含许多项,加载所需的时间可能会导致用户界面出现明显延迟。您可以通过将 VirtualizingStackPanel.IsVirtualizing 附加属性设置为 true 来缩短加载时间。当用户使用鼠标滚轮或拖动滚动条的拇指滚动 TreeView 时,UI 的反应也可能很慢。您可以通过将 VirtualizingStackPanel.VirtualizationMode 附加属性设置为 Recycling 来提高用户滚动时 TreeView 的性能。
How to: Improve the Performance of a TreeView
XAML:
XAML:
<TreeView Height="200" ItemsSource="{Binding Source={StaticResource dataItems}}" x:Name="myTreeView"
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"/>
Programmatically:
以编程方式:
myTreeView.SetValue(VirtualizingStackPanel.IsVirtualizingProperty, true);
myTreeView.SetValue(VirtualizingStackPanel.VirtualizationModeProperty, VirtualizationMode.Recycling)
回答by TomTom
Your problem is likely not rendering but layout - it has to instantiate a lot of UI elements to find the size of them so that it can properly size a number of UI elements (sliders), and this takes time. Rendering likely does not enter into this at all.
您的问题可能不是渲染而是布局 - 它必须实例化大量 UI 元素才能找到它们的大小,以便它可以正确调整多个 UI 元素(滑块)的大小,这需要时间。渲染可能根本不涉及这一点。

