Set TreeListView.SelectetItem is too slow when subtree init dynamically using GetChildren override

Grids for WPF Forum

Posted 11 months ago by Vadim Tsedrik
Version: 19.1.0683
Platform: .NET 4.8
Environment: Windows 10 (64-bit)

Hello, currently we are using in our product TreeListView for WPF and we have big problem when navigating through huge tree.
Our test case contains about 5000 nodes with maximum 6 nesting depth.

Tree looks like:

group B,C,D can contains 1000 nodes in each subgroup. Indexes created dynamically when navigating by tree, and depends on metadata of each variable.

Also class VariableTreeListBoxItemAdapter : TreeListBoxItemAdapter is using for better performance, with override

public override IEnumerable GetChildren(TreeListBox ownerControl, object item)
    var model = item as VarsTreeItem;
    return model != null ? model.Children : null
public ObservableCollection<VarsTreeItemBase> Children
   if (_children == null)
      if (VarMetadata != null)
     return _children;
The  actual problem that binding to SelectedItem in TreeListView from AutoCompleteBox calls GetChildren() from VariableTreeListBoxItemAdapter for all 5000 nodes that created before selected if try to select last node in tree from AutoCompleteBox collection. And this call takes more than 50 seconds in UI thread. If node selected from first group the delay is not so big, and not visible by user.

VarsTreeItemBase.Children property used lazy loading and created elements only for groups and subgroups. Subtree for any variable created in Children property. So when user try to expand elements subtree creates dynamically and fast.
But when user select last item or in the middle of tree from AutoCompleteBox creating of 5000 previous elements in tree is too slow and hangs UI thread using TreeListBoxItemAdapter.
Could you suggest how i can fix the issue?

[Modified 11 months ago]

Comments (6)

Posted 11 months ago by Actipro Software Support - Cleveland, OH, USA


One optimization you can do in your item adapter is override the CanHaveChildren method and return false for any nodes you quickly know for a fact will always be leaf nodes.  When that method returns false, it won't call GetChildren on for that node.

Pair that with setting the item adapter's ChildrenQueryModeDefault property to TreeItemChildrenQueryMode.OnExpansion instead of OnDisplay.  This tells the control to always show an expander and not call GetChildren until the expander is actually clicked.  When this property is its default of OnDisplay, the GetChildren method will be called for each node so that it knows whether to show an expander or not, which is causing the slowdown for you since all the visible nodes above the selection are being examined.  Changing it to OnExpand prevents that slowdown.

If you want more precise control over the TreeItemChildrenQueryMode result for each node, you can override the item adapter's GetChildrenQueryMode method.  It returns the ChildrenQueryModeDefault property value by default.

Actipro Software Support

Posted 11 months ago by Vadim Tsedrik

Hello, thank you for quick feedback.

I tried both suggestions from you: in override CanHaveChildren and return false for definitely leaf node, also set TreeItemChildrenQueryMode.OnExpansion but it still doesn't help me if try to select variable in last group in case of previous groups contains nodes with a lot of Children.
You can see in image that 2nd and 3rd groups contains nodes that can have up to 20000 leafs. And when i try to search variable in 3rd or 4th group it takes me 40seconds to create all nodes for 1st,2nd,3rd groups that not needed for me now.

2nd group example:

search result from AutoCompleteBox

Maybe you can suggest how to change TreeListBoxItemAdapter to call GetChildren only inside search subtree? e.g. GroupD->SubgroupD->Variables and do not call for all other subgroups (GroupA, GroupB, GroupC)

Thank you

[Modified 11 months ago]

Posted 11 months ago by Actipro Software Support - Cleveland, OH, USA


Can you please put together a new simple sample project that shows this delay so that we can work with that and debug your situation to get you a solution?

When you have that ready, send it to our support address (or reply to the other ticket you originally created in the support system with it).  Make sure exclude the bin/obj folders from the ZIP you send so it doesn't get spam blocked.  Thanks!

Actipro Software Support

Posted 11 months ago by Vadim Tsedrik


I replied to the original ticket, please take a look the test project.

Note, that in real solution the result in 10 times slower in case of up to 1000000 leafs are created when only last node selected from AutoCompleteBox in last group.


Posted 11 months ago by Actipro Software Support - Cleveland, OH, USA

Hi Vadim,

Thank you for the sample.  What happens when you set the TreeListView.SelectedItem property is that it has to traverse the tree to look for the matching item to select.  Since you are selecting the very last item programmatically here in an enormous tree, it takes quite a bit of time to locate that item.

A better way to select it would be by "path" via the TreeListView.SelectItemByFullPath method.  That allows the control to just walk the path and instantly select the item.  That being said, each item must have a unique string path (at least unique with its siblings) for this to work.

To add this to your sample, I made several changes.  In the item adapter, I added this, which finds the path segment for a particular node:

public override string GetPath(TreeListBox ownerControl, object item) {
    var node = item as Node;
    return (node != null ? node.Caption : base.GetPath(ownerControl, item));

I added this to your Node class, which finds the full path (excludes the root item) for the node:

public string FullPath {
    get {
        var fullPath = new StringBuilder();
        var node = this;
        node = node._parent;
        while (node._parent != null) {
            fullPath.Insert(0, $"{node.Caption}\\");
            node = node._parent;
        return fullPath.ToString();

Then in your button event handler where you do the selection, I took out your SelectedItem setter statement and replaced it with:

var fullPath = lastNode.FullPath;
var success = Tlv1.SelectItemByFullPath(fullPath);

The node is instantly selected with those changes.

[Modified 11 months ago]

Actipro Software Support

Posted 11 months ago by Vadim Tsedrik

Thank you, provided solution works fine!

The latest build of this product (v21.1.1) was released 3 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.