Filter / search the shell tree

Shell for WPF Forum

Posted 6 years ago by Miguel A.
Avatar

Hi,

would be amazing to have the shell tree has filter / search possibilities like your treelistbox for example.

Comments (6)

Posted 6 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Miguel,

ShellTreeListBox inherits our Grids' TreeListBox control, so anything you can do in TreeListBox, you should be able to do in ShellTreeListBox as well.


Actipro Software Support

Posted 6 years ago by Miguel A.
Avatar

Hi,

in this case it seems that AutoExpandItemsOnFilter doesn't work. It filters items but doesn't expand folders. This is how I'm using it (same as TreeListBox where elements get expanded).

//edit: It does auto expand items but only after all have been expanded once first. I believe it lazy enumerates children for performance reasons. Could this be fixed? I mean when autoexpanditemsonfilter is set to true and we filter, it is expected to go through all items by expanding them. Otherwise the only workaround would be calling ExpandAll() followed by CollapseAll() on start, which delays the start for all users even when they don't use the filter.

 

<TextBox Name="textBox"
	Text="{Binding Source={x:Reference stringFilter}, Path=Value, Mode=TwoWay, ValidatesOnDataErrors=True, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged}"
</TextBox>

<shell:ShellTreeListBox
                    Name="treeList"
                    AutoExpandItemsOnFilter="True"
                    CanDragItems="True"
                    CanIncludeFiles="True"
                    CanIncludeLinks="True"
                    IsDefaultItemContextMenuEnabled="False"
                    IsFilterActive="{Binding ElementName=textBox, Path=HasText}"
                    IsRenamingEnabled="True">
                    <grids:TreeListBox.DataFilter>
                        <local:TreeNodeModelStringFilter x:Name="stringFilter" />
                    </grids:TreeListBox.DataFilter>
</shell:ShellTreeListBox>					

 

    public class TreeNodeModelStringFilter : StringFilterBase
    {
        public override DataFilterResult Filter(object item, object context)
        {
            var source = item is ShellObjectViewModel model ? model.Name : null;

            return FilterByString(source, Value) ? IncludedFilterResult : DataFilterResult.IncludedByDescendants;
        }
    }

[Modified 6 years ago]

Posted 6 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Miguel,

Enumerating the shell objects and recursing down it takes an enormous amount of time. So yes, as you suspected, the folders are lazy-loaded on expansion to avoid a very massive performance bottleneck. If we would recurse the entire hard drive, it could take minutes to do so. Further, portions of the Windows shell return results asynchronously. The results pop in at a time after the initial expansion request.  With that being said, I'm not sure of how we could support your request in a performant way.


Actipro Software Support

Posted 6 years ago by Miguel A.
Avatar

Hi,

I don't expect it to be performant and I know that depending on how deep it goes, it can take a great while. But when a developer enables auto expand on filter, he/she knows what that brings up with when displaying hard drive paths.

So I expect that autoexpandonfilter does what it says. When the filter starts it expands all nodes, no matter if it takes long or not or if the content is lazy loaded. It just should do what it says and expand them and search within the children. Because when a developer not wants this, he/she can disable autoexpandonfilter then, which makes more sense. For example when the developer displays the root of a hard drive.

As a developer you know what content it might can have and you are responsible yourself when it comes to what your program does. When you display the root of a hard dive you might not want it to go all the way down yes. But when you just display a folder and some sub folders for example, you might want it to expand all but currently you cannot.

If you don't plan to make changes on this, can you tell me a workaround then? Is there anything I can override or do myself to make it look into each folder without doing expandall -> collapseall at start?

//edit: I tried calling RefreshChildren() but unfortunately it only refreshs the children of the IShellObject but does not add them to ShellObjectViewModel children collection which is used for the filter mechanism and I couldn't find a way to update the children myself without changing the expanded state.

 

public class TreeNodeModelStringFilter : StringFilterBase
    {
        public override DataFilterResult Filter(object item, object context)
        {
            var model = item as ShellObjectViewModel;
            var source = model?.Name;
            if (model != null && model.CanHaveChildFolders && model.Children.Count == 0)
                model.Model.RefreshChildren();
            return FilterByString(source, Value) ? IncludedFilterResult : DataFilterResult.IncludedByDescendants;
        }
    }

 A (laggy) workaround would be (still wish RefreshChildren would update the children, then I only need to call it once instead of toggling expanded state all over again) :

static class ShellObjectViewModelExtensions
    {
        public static void RecursiveExpandOnFilter(this ShellObjectViewModel model)
        {
            if (model.Kind != ShellObjectKind.Folder) return;
            if (model.Children.Count == 0 && !model.IsExpanded)
            {
                model.IsExpanded = true;
                model.IsExpanded = false;
            }
            foreach (var v in model.Children)
            {
                RecursiveExpandOnFilter(v);
            }
        }
    }
	
	public class TreeNodeModelStringFilter : StringFilterBase
    {
        public override DataFilterResult Filter(object item, object context)
        {
            var model = item as ShellObjectViewModel;
            var source = model?.Name;
            model?.RecursiveExpandOnFilter();
            return FilterByString(source, Value) ? IncludedFilterResult : DataFilterResult.IncludedByDescendants;
        }
    }

[Modified 6 years ago]

Posted 6 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Miguel,

Due to the holiday, we probably won't get a chance to look into this in detail to see what's happening until after the new year.  We'll get back to you at that point. 


Actipro Software Support

Posted 6 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Miguel,

We've got a preview build with this change ready to test:

Updated TreeListBox to recursively search the tree for filter results as appropriate when the TreeItemChildrenQueryMode.OnExpansion option is used and TreeListBox.AutoExpandItemsOnFilter is set. In lazy-load scenarios where there are large load times (e.g. database or file system access), keep the AutoExpandItemsOnFilter property false when filtering to prevent initial display performance.

If you write our support address, we will send you the preview build to test.  Note that keeping AutoExpandItemsOnFilter set and filtering and pointing the ShellTreeListBox to any kind of root system folder with a lot of nested shell items will definitely affect performance in a very negative way.  But as you said, this is the way it should perform and you as a developer will have the chance to disable that auto-expand option for those kinds of scenarios.


Actipro Software Support

The latest build of this product (v24.1.3) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.