虚拟化技术
第一次接触虚拟化技术,是因为自定了TreeView控件,当子节点有特别多的内容,比如4000条的时候,展开子节点的时候大概要等待20多秒(跟计算机配置相关),这样效果无法忍受,以前只是见过虚拟化技术,但都是默认的,结果自己写的这个控件却没有。只能上学习了。引用以为高人的总结如下:
- WPF 中的 VirtualizingStackPanel 只支持一层数据的 UIV。(这一点好像在 WPF3.5 SP1 后有所改善?)
- WPF3.5 SP1 以前的 TreeView 是不支持 UIV的。而之后的 TreeView 在默认情况下 UIV 处于关闭状态,需要手动打开。
- 实现 UIV 需要一个对应的 ScollViewer。
- ScollViewer 中的 CanContentScroll 属性为 True 时,子对象才能实现 UIV。
该属性为 True 时,ScollViewer 在 Measure 时会把当前的 ViewPort 大小传给 Content 元素。否则,它会把 Infinite 传给 Content。
同时,由子元素(也就是 VirtualizingStackPanel)需要实现 IScollInfo 并返回 Scroll 相关信息,而 ScollViewer 则只是一个简单的视窗;这样,子元素就可以在内部实现 UIV,并告知其对应的 ScrollOwner(ScrollViewer) 相关的拖动信息。
所以,上面的 xaml 主要有两个错误:
- ScrollViewer.CanContentScroll 应该设置为 True。
- 应该把 VirtualizingStackPanel 作为 ScrollViewer 的内容元素(Content)。
看完这份总结,马上了解如何修改自己的控件了,首先TreeViewItem不用动了,需要修改的是TreeView中的
<ScrollViewer HorizontalScrollBarVisibility="Auto" CanContentScroll="{TemplateBinding ScrollViewer.CanContentScroll}"
VerticalScrollBarVisibility="Auto" Focusable="False"
Core:ScrollSynchronizer.HorizontalScrollGroup="H1">
<VirtualizingStackPanel x:Name="ItemsHost" IsItemsHost="True" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" Height="Auto"/>
</ScrollViewer>
使用地方
<TreeView ScrollViewer.CanContentScroll="True" VirtualizingStackPanel.IsVirtualizing="True"/>