Como usar a virtualização da interface do usuário com modelos ListBox redefinidos

Estou tentando usar o ListBox como uma exibição que contém vários itens e, é claro, preciso usar a virtualização da interface do usuário.

O problema é que a virtualização funciona apenas quando declaro o ListBox desta maneira:

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

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

Mas se eu tentar personalizá-lo, ele não será mais virtualizado:

<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>

Até onde eu descobri, este exemplo contém exatamente o mesmo que o ListBox contém por padrão. Mas a virtualização não está funcionando. Eu li vários artigos e também algumas respostas aqui, mas ainda não consigo descobrir a "maneira geral" - o que e onde devo definir, vincular, adicionar etc. para fazer a virtualização funcionar com modelos personalizados?