MultiSelectTreeView
MultiSelectTreeView copied to clipboard
Slow when expanding node with 20.000 items
first of all, thanks for sharing such a wonderful, well written and feature rich control. This is something that actually should be part of the framework but it isn't. So, thx for sharing this control.
One issue I came across while testing the control, it's extremely slow when a node with 20.000 items is expanded. Using the standard wpf treeview control, the folder expansion is instantaneously. Using the multiselecttreeview it takes minutes (!). Is this bad performance by design or is this a bug which can be fixed?
This probably needs UI virtualisation. There might be other issue entries about that. I've messed with virtualisation in a simple ListBox control and I'm not intending to do that for a control as complex as a TreeView, to be honest. There's all sorts of trouble around this and the first thing you lose is proper keyboard navigation and selection handling (because items do not visually exist at all times).
You might want to take a look at the origin project of MultiSelectTreeView, called TreeViewEx. I've read about UI virtualisation there in the past but don't know whether it's actually been completed sucessfully.
Thanks for the fast reply!
I'm not sure if it is only the lack of virtualization which makes it slow. During debugging, I found out that the method RecursiveTreeViewItemEnumerable is executed 20.000 times (for each node) which enumerates all nodes. I'm not sure why it is necessary to iterate 20.000 times through 20.000 nodes. One time should suffice, right?
This needs further investigation. Do you also see where these calls come from? Maybe some caching would help. Unfortunately I don't have profiler tools at hand right now.
This sounds like a problem I ran across recently in a tree with lazy loading. When the node had a large number of children, it would hang the UI for a minute or more when I expanded it. Upon digging around some, I noticed the same thing Stefan did: RecursiveTreeViewItemEnumerable is executed for every child.
When MultiSelectTreeViewItem.ItemsSource is set initially, it raises a collection reset event. This, in turn, runs some code to see if anything needs to be removed from the selected items in the tree, which ultimately calls RecursiveTreeViewItemEnumerable.
One easy win is to add a short-circuit to the if statement on line 699 for the initial assignment of ItemsSource. You could technically do it for any case where the old ItemsSource was null/empty prior to the reset.
Changing-up how things are done (e.g., caching the items) may render that change moot, though.
Any chance you can elaborate on this short-circuit?
I'm finding that the collection reset event is fired any time the ItemsSource is modified, which occurs when the tree is expanded, however I am having difficulty distinguishing it from the initial load.
Is there any fixes for this?