22

I have a ListBox that may have many rows of templated DB records, including an Image, bound to an ObservableCollection<MyItem>. Sometimes the collection could hold thousands of items.

The performance is great, but the scrolling is the default jumpy behavior. I would like it to have smooth scrolling, so I unchecked ScrollViewer.CanContentScroll.

Now I have smooth scrolling, but the performance is horrendous: the data is retrieved in a separate thread, and the thread finishes quickly, but it takes 10-20 seconds for the results to show in the ListBox. I assume that this is because unchecking ScrollViewer.CanContentScroll changes the underlying VirtualizingStackPanel to a regular StackPanel and so it is loading the entire collection before displaying the results.

So my question is this: how do I retain the the smooth scrolling without sacrificing the VirtualizingStackPanel behavior and performance?

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
Joel Cochran
  • 7,139
  • 2
  • 30
  • 43
  • 8
    http://stackoverflow.com/questions/1977929/wpf-listbox-with-a-listbox-ui-virtualization-and-scrolling/9875475 VirtualizingPanel.ScrollUnit="Pixel" – Guillaume Nov 20 '12 at 13:09
  • You can have both smooth scrolling and virtualization if you're prepared to use a little hack. See [this answer](http://stackoverflow.com/questions/1977929/wpf-listbox-with-a-listbox-ui-virtualization-and-scrolling/9875475#9875475) to a similar question for details. – Samuel Jack Mar 26 '12 at 16:34

3 Answers3

11

When you uncheck CanContentScroll, you lose virtualization. And the answer is really frustrating: For now there is no out-of-the-box solution :(.

PS: This is not the first post here, asking this very question.

Community
  • 1
  • 1
Anvaka
  • 15,658
  • 2
  • 47
  • 56
  • I was afraid of that but had to ask. I searched before asking but didn't find that post. I might dig just a little bit more, but time is limited so I'll have to lose Smooth Scrolling for now. – Joel Cochran Dec 17 '09 at 21:04
5

If you use .NET 4.5 (or 4.0 if you're willing to hack a bit) then there's an answer over here.

[Note that @Guilluame's comment was here way before this answer but it wasn't particularly visible when skimming for answers.]

Community
  • 1
  • 1
Zodman
  • 3,178
  • 2
  • 32
  • 38
2

For anyone searching at 2021 you can use solution like this:

You will keep scrolling and virtualization at the same time

            <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>
Tomáš Filip
  • 727
  • 3
  • 6
  • 23