diff --git a/Terminal.Gui/Views/ITreeViewFilter.cs b/Terminal.Gui/Views/ITreeViewFilter.cs
new file mode 100644
index 000000000..6f9aa5afc
--- /dev/null
+++ b/Terminal.Gui/Views/ITreeViewFilter.cs
@@ -0,0 +1,14 @@
+namespace Terminal.Gui {
+
+ ///
+ /// Provides filtering for a .
+ ///
+ public interface ITreeViewFilter where T : class {
+
+ ///
+ /// Return if the should
+ /// be included in the tree.
+ ///
+ bool IsMatch (T model);
+ }
+}
\ No newline at end of file
diff --git a/Terminal.Gui/Views/TreeView/TreeView.cs b/Terminal.Gui/Views/TreeView/TreeView.cs
index 5786315f9..3d5cbe889 100644
--- a/Terminal.Gui/Views/TreeView/TreeView.cs
+++ b/Terminal.Gui/Views/TreeView/TreeView.cs
@@ -214,6 +214,13 @@ namespace Terminal.Gui {
CursorVisibility desiredCursorVisibility = CursorVisibility.Invisible;
+ ///
+ /// Interface for filtering which lines of the tree are displayed
+ /// e.g. to provide text searching. Defaults to
+ /// (no filtering).
+ ///
+ public ITreeViewFilter Filter = null;
+
///
/// Get / Set the wished cursor when the tree is focused.
/// Only applies when is true.
@@ -545,7 +552,12 @@ namespace Terminal.Gui {
List> toReturn = new List> ();
foreach (var root in roots.Values) {
- toReturn.AddRange (AddToLineMap (root));
+
+ var toAdd = AddToLineMap (root, false, out var isMatch);
+ if(isMatch)
+ {
+ toReturn.AddRange (toAdd);
+ }
}
cachedLineMap = new ReadOnlyCollection> (toReturn);
@@ -555,17 +567,44 @@ namespace Terminal.Gui {
return cachedLineMap;
}
- private IEnumerable> AddToLineMap (Branch currentBranch)
+ private bool IsFilterMatch (Branch branch)
{
- yield return currentBranch;
+ return Filter?.IsMatch(branch.Model) ?? true;
+ }
+
+ private IEnumerable> AddToLineMap (Branch currentBranch,bool parentMatches, out bool match)
+ {
+ bool weMatch = IsFilterMatch(currentBranch);
+ bool anyChildMatches = false;
+
+ var toReturn = new List>();
+ var children = new List>();
if (currentBranch.IsExpanded) {
foreach (var subBranch in currentBranch.ChildBranches.Values) {
- foreach (var sub in AddToLineMap (subBranch)) {
- yield return sub;
+
+ foreach (var sub in AddToLineMap (subBranch, weMatch, out var childMatch)) {
+
+ if(childMatch)
+ {
+ children.Add(sub);
+ anyChildMatches = true;
+ }
}
}
}
+
+ if(parentMatches || weMatch || anyChildMatches)
+ {
+ match = true;
+ toReturn.Add(currentBranch);
+ }
+ else{
+ match = false;
+ }
+
+ toReturn.AddRange(children);
+ return toReturn;
}
///
@@ -1290,9 +1329,9 @@ namespace Terminal.Gui {
}
///
- /// Clears any cached results of
+ /// Clears any cached results of the tree state.
///
- protected void InvalidateLineMap ()
+ public void InvalidateLineMap ()
{
cachedLineMap = null;
}
diff --git a/Terminal.Gui/Views/TreeViewTextFilter.cs b/Terminal.Gui/Views/TreeViewTextFilter.cs
new file mode 100644
index 000000000..b861f08ae
--- /dev/null
+++ b/Terminal.Gui/Views/TreeViewTextFilter.cs
@@ -0,0 +1,65 @@
+using System;
+
+namespace Terminal.Gui {
+
+ ///
+ /// implementation which searches the
+ /// of the model for the given
+ /// .
+ ///
+ ///
+ public class TreeViewTextFilter : ITreeViewFilter where T : class {
+ readonly TreeView _forTree;
+
+ ///
+ /// Creates a new instance of the filter for use with .
+ /// Set to begin filtering.
+ ///
+ ///
+ ///
+ public TreeViewTextFilter (TreeView forTree)
+ {
+ _forTree = forTree ?? throw new ArgumentNullException (nameof (forTree));
+ }
+
+ ///
+ /// The case sensitivity of the search match.
+ /// Defaults to .
+ ///
+ public StringComparison Comparer { get; set; } = StringComparison.OrdinalIgnoreCase;
+ private string text;
+
+ ///
+ /// The text that will be searched for in the
+ ///
+ public string Text {
+ get { return text; }
+ set {
+ text = value;
+ RefreshTreeView ();
+ }
+ }
+
+ private void RefreshTreeView ()
+ {
+ _forTree.InvalidateLineMap ();
+ _forTree.SetNeedsDisplay ();
+ }
+
+ ///
+ /// Returns if there is no or
+ /// the text matches the of the
+ /// .
+ ///
+ ///
+ ///
+ public bool IsMatch (T model)
+ {
+ if (string.IsNullOrWhiteSpace (Text)) {
+ return true;
+ }
+
+ return _forTree.AspectGetter (model)?.IndexOf (Text, Comparer) != -1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/UICatalog/Scenarios/ClassExplorer.cs b/UICatalog/Scenarios/ClassExplorer.cs
index d4d692f5b..79992b307 100644
--- a/UICatalog/Scenarios/ClassExplorer.cs
+++ b/UICatalog/Scenarios/ClassExplorer.cs
@@ -83,11 +83,30 @@ namespace UICatalog.Scenarios {
_treeView = new TreeView