Filtering an Actipro TreeListBox in WPF


Overview

This article demonstrates two approaches to filtering a TreeListView using Actipro's WPF controls. Each approach is illustrated with code examples for straightforward implementation (translation: copy/paste).

Option 1: Filtering with PredicateFilter

This method demonstrates creating a simple Filter function to dynamically control node visibility in a TreeListBox. When the filter text is empty, the filter is effectively reset, making all items visible again.

/// <summary>
/// Filters nodes displayed in the TreeListBox based on the provided text.
/// </summary>
/// <param name="filterText">The text used to filter nodes.</param>
public void Filter(string filterText)
{
    this.TreeListBox.IsFilterActive = true;
    this.TreeListBox.DataFilter = new PredicateFilter(i =>
    {
        var node = i as TreeNode;
        string? name = node?.Name;
        return name != null && name.StartsWith(filterText);
    });
}

Option 2: Filtering by Extending StringFilterBase

This approach involves creating a subclass of Actipro's StringFilterBase and overriding its Filter method. It provides a reusable filtering strategy specifically designed for string-based node filtering scenarios. In this example the TreeNodeFilter we'll add the to the TreeListBox via XAML.

/// <summary>
/// Provides a reusable, string-based filter implementation tailored for tree node models.
/// </summary>
public class TreeNodeFilter : StringFilterBase
{
    /// <summary>
    /// Evaluates whether the specified item meets the filtering criteria.
    /// </summary>
    /// <param name="item">The item to evaluate against the filter criteria.</param>
    /// <param name="context">Optional contextual information for the filtering operation.</param>
    /// <returns>A <see cref="DataFilterResult"/> indicating the outcome of the filtering process.</returns>
    public override DataFilterResult Filter(object item, object context)
    {
        var source = (item is TreeNode model ? model.Name : null);
        return this.FilterByString(source, this.Value) ? this.IncludedFilterResult : DataFilterResult.IncludedByDescendants;
    }
}
<grids:TreeListBox
		AlternationCount="2"
		IsRootItemVisible="True">
		<grids:TreeListBox.DataFilter>
				<t:TreeNodeFilter x:Name="Filter" />
		</grids:TreeListBox.DataFilter>
</grids:TreeListBox>

Both options provide efficient, clear ways to implement filtering functionality tailored to your application's needs using Actipro's comprehensive WPF controls. Although I'm just doing a simple contains on a single property it could be updated to use regular expressions, make database calls or filter on multiple properties (noting that with large lists this would add additional override, so mileage may vary).