4

I've been checking out the UI virtualization feature for WPF's TreeView control, which as I understand, is available since .NET 3.5 SP1.

I made a simple project to make sure that UI virtualization is performed correctly, and found out that it doesn't work at all - all of the items are retrieved rather than just the ones currently displayed on the screen.

My XAML looks like this

<TreeView x:Name="myTree" Height="150" ItemsSource="{Binding Items}"
          VirtualizingStackPanel.IsVirtualizing="True"
          VirtualizingStackPanel.VirtualizationMode="Standard"
          ScrollViewer.IsDeferredScrollingEnabled="True" />

And my code behind

    public IEnumerable Items { get; set; }

    public MainWindow()
    {
        Items = GenerateList();
        this.DataContext = this;

        InitializeComponent();
    }

    private IEnumerable GenerateList()
    {
        MyList list = new MyList();

        for (int i = 0; i < 1000; i++)
        {
            list.Add("Item " + i);
        }

        return list;
    }

Note that MyList is my own implementation of IList that holds an ArrayList and does nothing more than forward calls to the held ArrayList and write to the console which method/property was called. For example:

public object this[int index]
{
    get
    {
        Debug.WriteLine(string.Format("get[{0}]", index));
        return _list[index];
    }
    set
    {
        Debug.WriteLine(string.Format("set[{0}]", index));
        _list[index] = value;
    }
}

If I replace my TreeView with a ListBox, UI virtualization works as expected - i.e. only ~20 items are requested and not the whole 1000.

Am I doing something wrong here?

EDIT

I've also tried replacing the default ItemsPanel to VirtualizingStackPanel, as suggested , but I'm getting the same results.

1 Answer 1

2

Default ItemsPanelTemplate for TreeView is StackPanel and not VirtualizingStackPanel that's why you can't see virtualization in it. Whereas for ListBox default ItemsPanelTemplate is VirtualizingStackPanel that's why setting VirtualizingStackPanel.IsVirtualizing="True" works for ListBox.

To enable virtualization on your TreeView apart from setting property VirtualizingStackPanel.IsVirtualizing="True", you need to override the its default itemsPanelTemplate like this -

<TreeView x:Name="myTree" Height="150" ItemsSource="{Binding Items}"
          VirtualizingStackPanel.IsVirtualizing="True"
          VirtualizingStackPanel.VirtualizationMode="Standard"
          VirtualizingStackPanel.CleanUpVirtualizedItem="myTree_CleanUpVirtualizedItem"
          ScrollViewer.IsDeferredScrollingEnabled="True">
    <TreeView.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel IsItemsHost="True" />                   
        </ItemsPanelTemplate>
    </TreeView.ItemsPanel>
</TreeView>
Sign up to request clarification or add additional context in comments.

8 Comments

I've already tried exactly that (the only difference being that I didn't set IsItemsHost="True", which I believe doesn't make a difference in this case - correct me if I'm wrong). Sorry I didn't mention it.
How you reached to the point that all 1000 items are fetched and virtualization is not coming into play. I tried hooking an event 'VirtualizingStackPanel.CleanUpVirtualizedItem' to the treeView and it gets called as soon as any item >20 comes in view. Check yourself by hooking that event and you will see that vistualization is working. Updated the answer. :)
You don't need to override the ItemsPanelTemplate, setting VirtualizingStackPanel.IsVirtualizing is enough.
@RV1987 I will only be able to check this tomorrow, but either way, I see that 1000 items are retrieved because I'm logging all access to the list's elements. When I use ListBox, only 20 items are accessed; when I use TreeView, all 1000 items are accessed. You can't argue with that no matter what you get by hooking that event.
@H.B. - Yeah, i just tested it and simply setting this property enables virtualization for TreeView and it seems to working fine at my end.:)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.