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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With