I have an ItemsControl
containing a list of data that I would like to virtualize, however VirtualizingStackPanel.IsVirtualizing="True"
does not seem to work with an ItemsControl
.
Is this really the case or is there another way of doing this that I am not aware of?
To test I have been using the following block of code:
<ItemsControl ItemsSource="{Binding Path=AccountViews.Tables[0]}"
VirtualizingStackPanel.IsVirtualizing="True">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Initialized="TextBlock_Initialized"
Margin="5,50,5,50" Text="{Binding Path=Name}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
If I change the ItemsControl
to a ListBox
, I can see that the Initialized
event only runs a handful of times (the huge margins are just so I only have to go through a few records), however as an ItemsControl
every item gets initialized.
I have tried setting the ItemsControlPanelTemplate
to a VirtualizingStackPanel
but that doesn't seem to help.
Building on DavidN's answer, here is a style you can use on an ItemsControl to virtualise it:
I do not like the suggestion to use a ListBox as they allow the selection of rows where you do not necessarily want it.
There's actually much more to it than just making the
ItemsPanelTemplate
useVirtualizingStackPanel
. The defaultControlTemplate
forItemsControl
does not have aScrollViewer
, which is the key to virtualization. Adding to the the default control template forItemsControl
(using the control template forListBox
as a template) gives us the following:(BTW, a great tool for looking at default control templates is Show Me The Template)
Things to notice:
You have to set
ScrollViewer.CanContentScroll="True"
, see here for why.Also notice that I put
VirtualizingStackPanel.VirtualizationMode="Recycling"
. This will reduce the numbers of timesTextBlock_Initialized
is called to however many TextBlocks are visible on the screen. You can read more on UI virtualization here .EDIT: Forgot to state the obvious: as an alternate solution, you can just replace
ItemsControl
withListBox
:) Also, check out this Optimizing Performance on MSDN page and notice thatItemsControl
isn't in the "Controls That Implement Performance Features" table, which is why we need to edit the control template.It is just that the default
ItemsPanel
isn't aVirtualizingStackPanel
. You need to change it: