none
Default ItemsControl not virtualizing RRS feed

  • Question

  • Hi,

    I have run into a problem with the default ItemsControl - it seems that it's not properly virtualizing. I've implemented the following XAML:

    <ItemsControl ItemsSource="{Binding Source={StaticResource TestData}, XPath=*}"
        <ItemsControl.Template> 
            <ControlTemplate TargetType="{x:Type ItemsControl}"
                <ScrollViewer CanContentScroll="True"
                    <ItemsPresenter /> 
                </ScrollViewer> 
            </ControlTemplate> 
        </ItemsControl.Template> 
    </ItemsControl> 
     

    TestData is a simple collection of 20 strings. The ItemTemplate binds to the string using a converter that outputs a debug statement, so I can track which item's loaded. I've made the Window so small that only one item can be shown.

    If I change my ItemsControl into a ListBox (by simply changing the tag) my debug output shows "Loading String1, Loading String2" - which is the correct behavior (the other 18 strings are not loaded as they're not visible).

    However, switching back to ItemsControl outputs "Loading String1 ... Loading String 20", i.e. virtualization does not occur... I don't want the user to be able to select the items, so I don't want to use a ListBox.

    The ListBox template however does not show something more than embedding the ItemsPresenter into a ScrollViewer - similar to what I'm doing, so I don't know what the difference can be! Also, the ItemsControl is in a Grid, so it's only allocated the space it has. It seems that the ListBox does something to the ScrollViewer to make the virtualizingstackpanel do its thing...

    Is there anything I'm forgetting?

    Thanks!
    Saturday, August 9, 2008 8:16 PM

Answers

  • UI virtualization by default doesn't kick in for ItemsControl, you could replace ItemsControl's default ItemsPanelTemplate, and place VirtualizingStackPanel into it something like the following:

    <ItemsControl>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>

    You also need to introduce ScrollViewer into ItemsControl's control template, and set he ItemsPresenter as the child of ScrollViewer, UI Virtualization needs ScrollViewer to do its magic.

    Hope this helps
    • Edited by Marco Zhou Friday, August 15, 2008 9:41 AM add stuff
    • Marked as answer by Marco Zhou Friday, August 15, 2008 9:42 AM
    Wednesday, August 13, 2008 5:54 AM

All replies

  • UI virtualization by default doesn't kick in for ItemsControl, you could replace ItemsControl's default ItemsPanelTemplate, and place VirtualizingStackPanel into it something like the following:

    <ItemsControl>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>

    You also need to introduce ScrollViewer into ItemsControl's control template, and set he ItemsPresenter as the child of ScrollViewer, UI Virtualization needs ScrollViewer to do its magic.

    Hope this helps
    • Edited by Marco Zhou Friday, August 15, 2008 9:41 AM add stuff
    • Marked as answer by Marco Zhou Friday, August 15, 2008 9:42 AM
    Wednesday, August 13, 2008 5:54 AM
  • Hi Marco

    I have the same problem. Should this work?

    <ItemsControl> 
        <ItemsControl.Template> 
            <ControlTemplate TargetType="ItemsControl">  
                <Border> 
                    <ScrollViewer> 
                        <ItemsPresenter/> 
                    </ScrollViewer> 
                </Border> 
            </ControlTemplate> 
        </ItemsControl.Template> 
        <ItemsControl.ItemsPanel> 
            <ItemsPanelTemplate> 
                <VirtualizingStackPanel IsItemsHost="True"/>  
            </ItemsPanelTemplate> 
        </ItemsControl.ItemsPanel> 
    </ItemsControl> 

    the ItemsSource is set programmatically at runtime to an IList<>

    Hope you can help
    Thank you

    Edit:
    <ItemsControl.Template> 
            <ControlTemplate TargetType="ItemsControl">  
                <Border> 
                    <ScrollViewer CanContentScroll="True">  
                        <VirtualizingStackPanel IsItemsHost="True"/>  
                    </ScrollViewer> 
                </Border> 
            </ControlTemplate> 
        </ItemsControl.Template> 
    It appears CanContentScroll=True on ScrollViewer does the trick for virtualization. The only problem now is that scrolling scrolls a whole ContentPresenter item. I would like to have normal scrolling because my ContentPresenter is bigger then the visual area... ill try to override the scrolling if it is possible.

    Any thoughts appreciated
    • Edited by Stefan U7 Wednesday, October 8, 2008 1:58 AM
    Tuesday, October 7, 2008 10:16 AM