wpfxamllistboxvirtualizationui-virtualization

How to use UI virtualization with redefined ListBox templates


I'm trying to use ListBox as a view containing multiple items and, of course, I need to use UI virtualization in it.

The problem is virtualization works only when I declare ListBox this way:

<ListBox 
    ItemsSource="{Binding ItemsSource}" 
    VirtualizingStackPanel.IsVirtualizing="True"
    VirtualizingStackPanel.VirtualizationMode="Recycling">

    <ListBox.ItemTemplate>
        <DataTemplate>
            <views:SiteEntryView />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

But if I try to customize it, it doesn't virtualizing anymore:

<ListBox 
    ItemsSource="{Binding ItemsSource}" 
    VirtualizingStackPanel.IsVirtualizing="True"
    VirtualizingStackPanel.VirtualizationMode="Recycling">

    <ListBox.Template>
        <ControlTemplate>
            <ScrollViewer>
                <ItemsPresenter />
            </ScrollViewer>
        </ControlTemplate>
    </ListBox.Template>

    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>

    <ListBox.ItemTemplate>
        <DataTemplate>
            <views:SiteEntryView />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

As far as I've found, this sample contains just the same that ListBox contains by default. But virtualization isn't working. I've read several articles and also couple of answers here, but still can't figure out the "general way" - what and where I must set, bind, add, etc to make virtualization work with custom templates?


Solution

  • The reason is that you're using a StackPanel for your ItemsPanel - you should be using a VirtualizingStackPanel instead (which is also the default ItemsPanel for ListBox).

    Either remove your ItemsPanel definition or modify it to use a VirtualizingStackPanel:

    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>