Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Virtualized ListView with AutoScroll Performance (Slow)

I have a listview bound to an observable collection of strings. This collection is added to very quickly (for times of up to 30 mins). It was running extremely slowly without virtualization on, I added that an it was great. However, after adding an extender that had the list autoscroll to the bottom, it was again very slow., I have the listview as follows:

<ListView  Background="Transparent"  
           ItemsSource="{
                  Binding Source={
                             StaticResource MyViewModel}
                         ,Path=MyList}" 
          VirtualizingStackPanel.IsVirtualizing="True"
          ScrollViewer.CanContentScroll="True"
          ScrollViewer.VerticalScrollBarVisibility="Visible">
        <ListView.ItemsPanel>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel/>
            </ItemsPanelTemplate>
        </ListView.ItemsPanel>
    </ListView>

To scroll to the end, I am using some extender that I found on the net:

/// <summary>
    /// This method will be called when the AutoScrollToEnd
    /// property was changed
    /// </summary>
    /// <param name="s">The sender (the ListBox)</param>
    /// <param name="e">Some additional information</param>
    public static void OnAutoScrollToEndChanged(
                         DependencyObject s
                       , DependencyPropertyChangedEventArgs e)
    {
        var listBox = s as ListBox;
        var listBoxItems = listBox.Items;
        var data = listBoxItems.SourceCollection as INotifyCollectionChanged;

        var scrollToEndHandler = 
              new NotifyCollectionChangedEventHandler(
            (s1, e1) =>
            {
                if (listBox.Items.Count > 0)
                {
                    object lastItem = listBox.Items[
                                        listBox.Items.Count - 1];
                    Action action = () =>
                    {
                        listBoxItems.MoveCurrentTo(lastItem);
                        listBox.ScrollIntoView(lastItem);


                    };
                    action.Invoke();
                }
            });

        if ((bool)e.NewValue)
            data.CollectionChanged += scrollToEndHandler;
        else
            data.CollectionChanged -= scrollToEndHandler;
    }

I do not know how the ScrollIntoView method works, but I am worried that it is negating the performance boost of virtualization. Another guess I have is that to scroll to a location in a list, it has to find the object rather than just jumping to an index.

So my question is: how do I have a listview that is updated very quickly with lots of entries that can scroll to the bottom without slowing down everything?

like image 586
gregsaab Avatar asked Mar 22 '26 02:03

gregsaab


1 Answers

Using listBox.ScrollIntoView(lastItem) updates the ListBox control for every item insert/delete/modify action.

Whenever ListBox item is getting modified, call listBox.SuspendLayout() and after inserting/deleting/modifying an item use listBox.ResumeLayout(). I believe this will solve your problem.

Also, if your ListBox is going to have lot of items; I recommend to use DoubleBufferedListBox which will help the control to update very smoothly.

like image 83
vcpmsc Avatar answered Mar 24 '26 16:03

vcpmsc



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!