2
votes

I'm trying to implement a virtualizing collection for hierarchical controls similar to the one for regular controls presented in this article.

The solution presented in the article relies heavily on the following behavior (from the article):

When an ItemsControl is bound to an IList implementation, rather than an IEnumerable implementation, it will not enumerate the entire list, and instead only accesses the items required for display. It uses the Count property to determine the size of the collection, presumably to set the scroll extents. It will then iterate through the onscreen items using the list indexer. Thus, it is possible to create an IList that can report to have a large number of items, and yet only actually retrieve the items when required.

I found that while ListBox has this behavior, TreeView (which is also an ItemsControl) doesn't behave like this, and all the items are always requested regardless of whether or not they're displayed on the screen.

So, is this a behavior specific just for ListBox and not for every ItemsControl or is it a bug in WPF's TreeView?

I've also been unable to find any mention of this behavior on MSDN, so if anyone finds it documented anywhere I'd love to know about it.

1
In the Remarks section of ItemsControl.ItemsPanel it says that the default ItemsPanel for ListBox is VirtualizingStackPanel, and here MSDN says that the default ItemsPanel for TreeView is an ordinary StackPanel. - Clemens
@Clemens This happens even when setting TreeView.ItemsPanel to VirtualizingStackPanel and turning on virtualization with VirtualizingStackPanel.IsVirtualizing="True". - Adi Lester
Ok, you could have mentioned that in your question. - Clemens

1 Answers

0
votes

There's more to Virtualizing an ItemsControl than just using a VirtualizingStackPanel or setting VirtualizingStackPanel.IsVirtualizing="True"

Here's the important bits of code needed, but see this question for more complete answer

<ItemsControl
    VirtualizingStackPanel.IsVirtualizing="True" <!-- needed -->
    ScrollViewer.CanContentScroll="True" <!-- needed -->
    ... >
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel /> <!-- needed -->
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.Template>
        <ControlTemplate>
            <ScrollViewer>  <!-- needed -->
                <ItemsPresenter  />
            </ScrollViewer>
        </ControlTemplate>
    </ItemsControl.Template>
</ItemsControl>