WPF 中的 ListBox、VirtualizingStackPanel 和平滑滚动

Posted

技术标签:

【中文标题】WPF 中的 ListBox、VirtualizingStackPanel 和平滑滚动【英文标题】:ListBox, VirtualizingStackPanel, and Smooth Scrolling in WPF 【发布时间】:2010-12-27 19:14:22 【问题描述】:

我有一个ListBox,它可能有很多行模板化数据库记录,包括绑定到ObservableCollection<MyItem>Image。有时集合可以容纳数千件物品。

性能很棒,但滚动是默认的跳跃行为。我希望它有平滑滚动,所以我取消选中ScrollViewer.CanContentScroll

现在我可以平滑滚动,但性能很糟糕:数据在单独的线程中检索,线程很快完成,但结果显示在ListBox 中需要 10-20 秒。我认为这是因为取消选中ScrollViewer.CanContentScroll 会将底层VirtualizingStackPanel 更改为常规StackPanel,因此它会在显示结果之前加载整个集合。

所以我的问题是:如何在不牺牲VirtualizingStackPanel 行为和性能的情况下保持平滑滚动?

【问题讨论】:

如果您准备使用一些小技巧,您可以同时拥有平滑滚动和虚拟化。有关详细信息,请参阅 this answer 到类似问题。 ***.com/questions/1977929/… VirtualizingPanel.ScrollUnit="Pixel" 【参考方案1】:

当您取消选中 CanContentScroll 时,您是 lose virtualization。答案确实令人沮丧:目前还没有开箱即用的解决方案:(。

PS:这里不是第一次发帖,问this very question。

【讨论】:

我很害怕,但不得不问。我在问之前搜索过,但没有找到那个帖子。我可能会再挖掘一点,但时间有限,所以我现在不得不失去平滑滚动。【参考方案2】:

如果您使用 .NET 4.5(或 4.0,如果您愿意破解一下),那么答案是 over here。

[请注意,@Guilluame 的评论在此答案之前就在这里,但在浏览答案时并不是特别明显。]

【讨论】:

【参考方案3】:

对于在 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>

【讨论】:

以上是关于WPF 中的 ListBox、VirtualizingStackPanel 和平滑滚动的主要内容,如果未能解决你的问题,请参考以下文章

如何在 WPF 中的 ListBox 上添加标签?

如何从 WPF 中的 ListBox 中删除边框?

WPF中Expander与ListBox(ItemsControl)嵌套中的问题

wpf listbox 绑定

如何在WPF中的ListBox上添加标签?

〝WPF〞中的〝ListBox〞、〝ListView〞和〝DataGridView〞有啥区别?