Virtualizando um ItemsControl?

Eu tenho um ItemsControl contendo uma lista de dados que gostaria de virtualizar, no entanto VirtualizingStackPanel.IsVirtualizing="True" não parece funcionar com um ItemsControl .

Isso é realmente o caso ou há outra maneira de fazer isso que eu não conheço?

Para testar, tenho usado o seguinte bloco de código:

        

Se eu alterar o ItemsControl para um ListBox , eu posso ver que o evento Initialized só é executado um punhado de vezes (as margens enormes são apenas para que eu só tenha que passar por alguns registros), no entanto como um ItemsControl cada item é inicializado.

Eu tentei definir o ItemsControlPanelTemplate para um VirtualizingStackPanel mas isso não parece ajudar.

Na verdade, há muito mais do que apenas fazer o ItemsPanelTemplate usar o VirtualizingStackPanel . O ControlTemplate padrão para ItemsControl não tem um ScrollViewer , que é a chave para a virtualização. Adicionar ao modelo de controle padrão para ItemsControl (usando o modelo de controle para ListBox como um modelo) nos dá o seguinte:

                      

(BTW, uma ótima ferramenta para olhar para modelos de controle padrão é Show Me The Template )

Coisas para perceber:

Você tem que definir ScrollViewer.CanContentScroll="True" , veja aqui o porquê.

Observe também que coloquei VirtualizingStackPanel.VirtualizationMode="Recycling" . Isso reduzirá o número de vezes que TextBlock_Initialized é chamado para quantos TextBlocks estiverem visíveis na canvas. Você pode ler mais sobre a virtualização da interface do usuário aqui .

EDIT: Esqueceu de indicar o óbvio: como uma solução alternativa, você pode apenas replace ItemsControl com ListBox 🙂 Além disso, confira esta página Otimizando desempenho no MSDN e observe que ItemsControl não está na tabela “Controles que implementam resources de desempenho”, é por isso que precisamos editar o modelo de controle.

Com base na resposta de DavidN, aqui está um estilo que você pode usar em um ItemsControl para virtualizar:

   

Eu não gosto da sugestão de usar um ListBox como eles permitem a seleção de linhas onde você não necessariamente quer.

É só que o ItemsPanel padrão não é um VirtualizingStackPanel . Você precisa mudar isso: