将ListView与数千个这样的项目一起使用:
<ListView ItemsSource="{Binding Items}"
VirtualizingPanel.ScrollUnit="Pixel"
VirtualizingPanel.VirtualizationMode="Recycling"
VirtualizingPanel.CacheLength="1,1">
<ListView.ItemTemplate>
<DataTemplate>
<local:ItemUserControl />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
如果我在ItemUserControl
中使每个项目具有不同的高度,我发现滚动速度非常慢。通过拖动拇指快速滚动,每个帧大约需要 200-250 ms 才能进行布局。
如果我将VirtualizationMode
更改为Standard
,则会降至70-110毫秒
如果我另外将ScrollUnit
更改为Item
,则会降至30-70毫秒
但如果我像以前一样保留所有内容并简单地强制每个项目都相同Height
,那么它会下降到 5-7 ms 。
此外,我发现在列表顶部滚动时,不同高度的滚动速度更快,而在底部滚动较慢。
我的猜测是,当重用ItemUserControl
更改Height
时,会导致整个ListView
的布局更新。虽然这并没有真正解释为什么它在开始时比在结束时表现更好。我也觉得这种速度差异有点难以置信。
任何人都可以更深入地了解WPF的布局系统,并解释为什么会这样?也许是一个可以实现&lt; 10ms布局时间和高度变化的解决方案?
答案 0 :(得分:0)
感谢DeanChalk质疑我的理智,这让我质疑WPF的理智,这导致了这个答案。
事实证明,虽然ListView
存在不同大小的项目问题,但ItemsControl
却没有。 ListView
继承自ItemsControl
,但必定会有一些问题导致问题。
所以使用ItemsControl
就是答案。
此代码将为ItemsControl
启用虚拟化,并使用与之前相同的指标,在快速滚动时执行大约20 ms的布局。
<ItemsControl ItemsSource="{Binding Items}"
VirtualizingPanel.ScrollUnit="Pixel"
VirtualizingPanel.VirtualizationMode="Recycling"
VirtualizingPanel.CacheLength="1,1"
VirtualizingPanel.IsVirtualizing="True"
ScrollViewer.CanContentScroll="True">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:ItemUserControl />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
它似乎仍然比它可能更慢,但它是可用的 滚动顶部与底部之间的速度差异仍然存在,我无法解释它。如果有人有一些见解,请发表评论。
答案 1 :(得分:0)
这一切都归结为滚动位置的大小/位置所需的数学。
A)如果项目都是固定大小,则滚动是Pixel:
B)如果项目的高度可变,但滚动是按项目:
C)如果项目的高度可变,并且滚动是Pixel:
可以对选项C进行一些优化,可能会也可能不会内置到WPF中:
基本上,行为C将始终是虚拟化项目列表的最坏情况,因为它可能需要加载所有项目,只是为了进行布局测量。