ListBox、VirtualizingStackPanel和WPF中的平滑滚动

22

我有一个 ListBox,其中包含许多模板化的数据库记录行,包括一个 Image,绑定到一个 ObservableCollection<MyItem>。有时集合可能会包含数千个项目。

性能很好,但滚动是默认的跳跃行为。我想让它具有平滑的滚动效果,因此取消了 ScrollViewer.CanContentScroll

现在我拥有平滑的滚动效果,但性能非常差:数据在单独的线程中检索,线程很快结束,但需要 10-20 秒才能在 ListBox 中显示结果。我认为这是因为取消 ScrollViewer.CanContentScroll 将底层的 VirtualizingStackPanel 改变成普通的 StackPanel,所以它在显示结果之前加载整个集合。

那么我的问题是:如何在不牺牲 VirtualizingStackPanel 的行为和性能的情况下保留平滑的滚动效果?


如果你愿意使用一些小技巧,你可以同时拥有平滑滚动和虚拟化。请参考这个答案中类似问题的详细信息。 - Samuel Jack
8
VirtualizingPanel.ScrollUnit="Pixel" 翻译为:虚拟化面板.ScrollUnit="像素"。 - Guillaume
3个回答

11

如果您取消选中 CanContentScroll,您将失去虚拟化。而且现在的答案真是令人沮丧:目前还没有现成的解决方案 :(。

附注:这不是第一篇在此提问相同问题的文章。


我本来就有点担心,但还是不得不问一下。在提问之前我进行了搜索,但没有找到那篇帖子。我可能会再深入一点,但时间有限,所以暂时放弃平滑滚动。 - Joel Cochran

5
如果您使用.NET 4.5(或者愿意稍微动些手脚的话,可以使用4.0版本),那么 这里 提供了解决方案。
请注意,在浏览回答时,@Guilluame的评论比本回答提前发布,但其并不十分显眼。

2

如果有人在2021年进行搜索,你可以使用以下解决方案:

你可以同时保持滚动和虚拟化。

            <ItemsControl x:Name="TestIC" Grid.Row="1"
                ScrollViewer.CanContentScroll="True"
                VirtualizingPanel.IsVirtualizing="True"
                VirtualizingPanel.VirtualizationMode="Recycling" >
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.Template>
                    <ControlTemplate>
                        <Border
                            Padding="{TemplateBinding Control.Padding}"
                            Background="{TemplateBinding Panel.Background}"
                            BorderBrush="{TemplateBinding Border.BorderBrush}"
                            BorderThickness="{TemplateBinding Border.BorderThickness}"
                            SnapsToDevicePixels="True">
                            <ScrollViewer Padding="{TemplateBinding Control.Padding}" Focusable="False">
                                <ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
                            </ScrollViewer>
                        </Border>
                    </ControlTemplate>
                </ItemsControl.Template>
            </ItemsControl>

不是 ListBox,所以这里没有选择选项。 :( - TravisWhidden

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