Searching TreeViews

Searching TreeViews is not trivial because of their hierarchical nature. Nodes typically reflect a context defined by in part by their parent nodes but also by additional content associated with the node.

For example, if a user searched the TreeView below for "Electronics", you may or may not want to include the child nodes in the results. Furthermore, if items contained detailed descriptions, you might want to add keywords to help in the search. So if a user typed for example "beard", you would probably want the "Trimmers/Shavers" node to be selected.

The AutoComplete control provides a good way to implement a search box to be used with the TreeView. In this sample, we build a flat searchArray with the full node paths and keywords and use that as an itemsSource for searching through the TreeView.

In addition to the 'itemsSource'and 'displayMemberPath' properties, we use the 'searchMemberPath' property to specify the name of the field that contains the keywords to include in the search. For example, try typing 'collect' or 'food' in the search box:

Electronics
Trimmers/Shavers
Tablets
Phones
Apple
Motorola
Nokia
Samsung
Speakers
Monitors
Shopkins
Train Sets
Science Kit
Play-Doh
Crayola
Coffeee Maker
Breadmaker
Solar Panel
Work Table
Propane Grill
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// This file locates: "Scripts/Lesson/C1Nav/Searching.js".
c1.documentReady(function () {
    var tree = wijmo.Control.getControl('#theTree');
    var search = wijmo.Control.getControl('#search');
 
    search.itemsSource = getSearchList(tree.itemsSource);
 
    search.selectedIndexChanged.addHandler(function (s, e) {
        if (s.selectedItem) {
            tree.selectedItem = s.selectedItem.item;
        }
    });
 
    function getSearchList(items, searchList, path) {
 
        // set defaults
        if (searchList == null) searchList = [];
        if (path == null) path = '';
 
        // add items and sub-items
        for (var i = 0; i < items.length; i++) {
            var item = items[i];
            searchList.push({
                item: item,
                path: path + item.Header,
                keywords: item.Keywords
            });
            if (item.Items) {
                getSearchList(item.Items, searchList, path + item.Header + ' / ');
            }
        }
        return searchList;
    }
});
1
2
3
4
5
6
7
8
9
// This file locates: "Content/css/Lesson/C1Nav/Searching.css".
.demo-control .wj-treeview {
    display:block;
    font-size: 120%;
    margin-bottom: 8px;
    padding: 6px;
    background: #f0f0f0;
    box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
using System.Web.Mvc;
 
namespace LearnMvcClient.Controllers
{
    public partial class C1NavController : Controller
    {
        // GET: Searching
        public ActionResult Searching()
        {
            return View(Models.TreeViewData.GetData(Url));
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@model IEnumerable<TreeViewData>
 
<h1>
    @Html.Raw(Resources.C1Nav.Searching_Title)
</h1>
<p>
    @Html.Raw(Resources.C1Nav.Searching_Text1)
</p>
<p>
    @Html.Raw(Resources.C1Nav.Searching_Text2)
</p>
<p>
    @Html.Raw(Resources.C1Nav.Searching_Text3)
</p>
<p>
    @Html.Raw(Resources.C1Nav.Searching_Text4)
</p>
 
<label for="search">@Html.Raw(Resources.C1Nav.Searching_Text5) </label>
@Html.C1().AutoComplete().Id("search").SelectedIndex(-1).DisplayMemberPath("path").SearchMemberPath("keywords")
@Html.C1().TreeView().Id("theTree").Bind(Model).DisplayMemberPath("Header").ChildItemsPath("Items")