WPF ListBox VirtualizingPanel.CacheLengthUnit=Item VirtualizingPanel.CacheLength=5,5

WPF ListBox VirtualizingPanel.CacheLengthUnit=Item VirtualizingPanel.CacheLength=5,5
Install-Package Microsoft.Extensions.DependencyInjection;

 

Totally speaking, VirtualizationPanel.CacheLengthUnit's value is item and its performance is better than pixel, the latter may lead to 

  • Unpredictable memory usage - Caches as many items as fit in the pixel range

  • Performance issues with variable-height items

  • Can cache too many items if items are small, wasting memory

  • Harder to optimize since item count varies based on content

 

VirtualizingPanel.CacheLengthUnit="Item"
VirtualizingPanel.CacheLength="5,5"

 

CacheLength="Before,After"First number (5) = Items cached BEFORE the visible viewportSecond number (5) = Items cached AFTER the visible viewportTotal cached items = 5 + 5 = 10 items (plus whatever is visible)

 

 

<ListBox ItemsSource="{Binding BooksCollection}"VirtualizingPanel.IsVirtualizing="True"VirtualizingPanel.VirtualizationMode="Recycling"VirtualizingPanel.CacheLengthUnit="Item"VirtualizingPanel.CacheLength="5,5"ScrollViewer.IsDeferredScrollingEnabled="True"ScrollViewer.CanContentScroll="True"><ListBox.ItemTemplate><DataTemplate><Grid><Grid.Resources><Style TargetType="TextBlock"><Setter Property="FontSize" Value="30"/><Setter Property="Width" Value="Auto"/><Style.Triggers><Trigger Property="IsMouseOver" Value="True"><Setter Property="FontSize" Value="50"/><Setter Property="Foreground" Value="Red"/></Trigger></Style.Triggers></Style></Grid.Resources><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/><ColumnDefinition/><ColumnDefinition/><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><TextBlock Text="{Binding Id}" Grid.Column="0"/><TextBlock Text="{Binding Name}" Grid.Column="1"/><TextBlock Text="{Binding Author}" Grid.Column="2"/><TextBlock Text="{Binding ISBN}" Grid.Column="3"/><TextBlock Text="{Binding Title}" Grid.Column="4"/><TextBlock Text="{Binding Topic}" Grid.Column="5"/></Grid></DataTemplate></ListBox.ItemTemplate>
</ListBox>public async Task InitBooksCollectionAsync()
{StatusMsg = $"Loading...,{GetMemory()},{GetTimeCost()}";BooksCollection = new ObservableCollection<Book>();List<Book> booksList = new List<Book>();for (int i = 1; i < 100000001; i++){booksList.Add(new Book(){Id = idService.GetID(),Author = $"Author_{i}",Name = nameService.GetName(),ISBN = isbnService.GetISBN(),Title = $"Title_{i}",Topic = $"Topic_{i}"});if (i < 1001 && i % 100 == 0){await PopulateBooksCollectionAsync(booksList);}else if (i > 1000 && i % 1000000 == 0){await PopulateBooksCollectionAsync(booksList);}}if (booksList.Any()){await PopulateBooksCollectionAsync(booksList);}StatusMsg = $"Loaded {BooksCollection.Count} items,{GetMemory()},{GetTimeCost()}";MessageBox.Show(StatusMsg);
}private async Task PopulateBooksCollectionAsync(List<Book> booksList)
{List<Book> tempList = new List<Book>();lock (objLock){tempList = booksList.ToList();booksList.Clear();}await Application.Current.Dispatcher.InvokeAsync(() =>{foreach (var book in tempList){BooksCollection.Add(book);}StatusMsg = $"Loaded {BooksCollection.Count} items,{GetMemory()},{GetTimeCost()}";}, DispatcherPriority.Background);
}private string GetMemory()
{var procMemory = Process.GetCurrentProcess().PrivateMemorySize64 / 1024.0d / 1024.0d;return $"Memory:{procMemory.ToString("#,##0.00")} M";
}private string GetTimeCost()
{return $"Time cost:{watch.Elapsed.TotalSeconds.ToString("#,##0.00")} seconds!";
}

 

 

 

 

image