TreeView
All collections widgets support virtualization: gameobjects created only for the visible items.
Add
Selectable
component to use keyboard and gamepad navigation.
Attention
Different TreeView’s cannot display the same nodes, unlike ListView, TileView, and Table.
Options
Options are almost same as the ListView, TileView and Table.
Nodes
ObservableList<TreeNode<TItem>>
Not available in the inspector window.
Deselect Collapsed Nodes
bool
Deselect nested nodes when parent node collapsed.
Scroll With Indent
bool
Scrolling with node indent in the secondary direction.
Container Max Size
bool
Prevent scrollbar blink caused by virtualization: the container will have the maximum width of all items. By default, the container has the maximum width of only visible items.RequireList Type
=List View with Variable Size
.
Get nodes
public TreeView Tree;
ObservableList<TreeNode<TreeViewItem>> nodes;
void Start()
{
if (Tree.Nodes == null)
{
Tree.Nodes = new ObservableList<TreeNode<TreeViewItem>>();
}
nodes = Tree.Nodes;
}
Get selected nodes
Tree.SelectedNodes.ForEach(x =>
{
// do something with selected node
Debug.Log(x.Item.Name);
var component = Tree.GetItemComponent(x.Index);
// not displayed component will be null
if (component != null)
{
component.DoSomething();
}
});
Add listeners
void AddListeners()
{
Tree.NodeSelected.AddListener(ProcessSelectedNode);
Tree.NodeDeselected.AddListener(ProcessDeselectedNode);
}
void ProcessSelectedNode(TreeNode<TreeViewItem> node)
{
Debug.Log("selected: " + node.Item.Name);
}
void void ProcessDeselectedNode(TreeNode<TreeViewItem> node)
{
Debug.Log("deselected: " + node.Item.Name);
}
Select node
Tree.SelectNode(nodes[1].Nodes[0]);
Select node with subnodes
Tree.SelectNodeWithSubnodes(nodes[1].Nodes[1]);
Deselect node
Tree.DeselectNode(nodes[1].Nodes[0]);
Deselect node with subnodes
Tree.DeselectNodeWithSubnodes(nodes[1].Nodes[1]);
Scroll to node
Tree.ScrollToAnimated(node);
Add node
var test_item = new TreeViewItem("added");
var test_node = new TreeNode<TreeViewItem>(test_item);
nodes.Add(test_node);
Hide nodes
nodes[1].IsVisible = false;
nodes[2].Nodes[1].IsVisible = false;
Collapse node
nodes[0].Nodes[0].IsExpanded = false;
Expand node
nodes[0].Nodes[0].IsExpanded = true;
Change node name
nodes[0].Item.Name = "Node renamed from code";
nodes[0].Nodes[1].Item.Name = "Another node renamed from code";
Sort
// Compare nodes by Name in ascending order
Comparison<TreeNode<TreeViewItem>> comparisonAsc = (x, y) => x.Item.Name.CompareTo(y.Item.Name);
// Compare nodes by Name in descending order
Comparison<TreeNode<TreeViewItem>> comparisonDesc = (x, y) => -x.Item.Name.CompareTo(y.Item.Name);
public void SortAsc()
{
using var _ = nodes.BeginUpdate();
ApplyNodesSort(nodes, comparisonAsc);
}
public void SortDesc()
{
using var _ = nodes.BeginUpdate();
ApplyNodesSort(nodes, comparisonDesc);
}
void ApplyNodesSort<T>(ObservableList<TreeNode<T>> nodes, Comparison<TreeNode<T>> comparison)
{
// apply sort for current nodes
nodes.Sort(comparison);
// apply sort for child nodes
nodes.ForEach(node =>
{
if (node.Nodes != null)
{
ApplyNodesSort(node.Nodes as ObservableList<TreeNode<T>>, comparison);
}
});
}
Filter nodes
public void Filter(string nameContains)
{
// Maintains performance while items are added/removed/changed
// by preventing the widgets from drawing
// until the EndUpdate() method is called
// or after value returned by BeginUpdate() was disposed.
using var _ = nodes.BeginUpdate();
SampleFilter(nodes, x => x.Name.Contains(nameContains));
}
bool SampleFilter(IObservableList<TreeNode<TreeViewItem>> nodes, Func<TreeViewItem,bool> filterFunc)
{
return nodes.Count(x =>
{
var have_visible_children = (x.Nodes==null) ? false : SampleFilter(x.Nodes, filterFunc);
x.IsVisible = have_visible_children || filterFunc(x.Item);
return x.IsVisible;
}) > 0;
}
Reset filter
public void ResetFilter()
{
using var _ = nodes.BeginUpdate();
nodes.ForEach(SetVisible);
}
void SetVisible(TreeNode<TreeViewItem> node)
{
if (node.Nodes != null)
{
node.Nodes.ForEach(SetVisible);
}
node.IsVisible = true;
}
Clear nodes
public void Clear()
{
nodes.Clear();
}
Nodes Serialization
You can use helper class TreeNodeJson<TItem>
for the node serialization and deserialization.
Warning
Unity JsonUtility
does not support recursive types so it cannot be used.
Newtonsoft.Json
can be used instead.
// serialize
var nodes = TreeNodeJson<TreeViewItem>.ConvertNodes(TreeView.Nodes);
var json = JsonConvert.SerializeObject(nodes);
// deserialize
var decoded = JsonConvert.DeserializeObject<TreeNodeJson<TreeViewItem>[]>(json);
TreeView.Nodes = TreeNodeJson<TreeViewItem>.ConvertNodes(decoded);