Filling a Treeview with content in UI-Toolkit

Hey there. I’m really new to the UI-Toolkit and currently I’m building a custom editor window that uses a TreeView, to display custom collections of Assets.
I tried all day to understand TreeViews and to display my Asset-Collections inside. It kind of works but when I want to display the child elements my TreeView breaks. And looks like this

This is my code for populating the Tree.

private void LoadCollectionTree()
{
    List<TreeViewItemData<TreeViewItem>> rootItems = new List<TreeViewItemData<TreeViewItem>>();
    int childId = 10000;

    foreach (AssetCollection collection in assetCollections)
    {
        //Create a root item for each collection
        TreeViewItem newItem = new AssetTreeItem(rootItems.Count, 0, collection.name); 
        List<TreeViewItemData<TreeViewItem>> childItems = new List<TreeViewItemData<TreeViewItem>>();

        //Loop through the assets to create child items
        foreach (Object asset in collection.assets)
        {
            if (asset != null && asset is Object)
            {
                TreeViewItem childItem = new AssetTreeItem(childId++, 1, asset.name);
                TreeViewItemData<TreeViewItem> childData = new TreeViewItemData<TreeViewItem>(childItem.id, childItem);
                childItems.Add(childData);
            }
        }
        TreeViewItemData<TreeViewItem> rootItemData = new TreeViewItemData<TreeViewItem>(newItem.id, newItem, childItems);
        rootItems.Add(rootItemData);
    }
    //Set root items to the tree view
    collectionTreeView.SetRootItems(rootItems);

    collectionTreeView.makeItem = () =>
    {
        VisualElement container = new VisualElement();
        container.style.flexDirection = FlexDirection.Row;

        Image icon = new Image();
        icon.style.width = 16;
        icon.style.height = 16;
        icon.style.marginRight = 4;
        container.Add(icon);

        Label label = new Label();
        container.Add(label);

        return container;
    };

    collectionTreeView.bindItem = (VisualElement element, int index) =>
    {
        if (index >= 0 && index < rootItems.Count)
        {
            TreeViewItemData<TreeViewItem> itemData = rootItems[index];
            AssetTreeItem item = itemData.data as AssetTreeItem; 

            VisualElement container = element;
            Image icon = container.Q<Image>();
            Label label = container.Q<Label>();

            icon.image = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/Editor/Resources/Icons/Collection-Icon.png");
            label.text = item.DisplayName; 
        }
    };
}

I would really appreciate some help!

I think you might be using TreeViewItem mistakingly thinking it’s part of the UI toolkit API. It’s from the old IMGUI API: Unity - Scripting API: TreeViewItem

Not sure if that makes a difference though, but you could just use TreeViewItemData<YourAssetType> directly rather than the extra layer of encapsulation.

Hard to tell what’s going wrong from the image. It looks like perhaps the last items aren’t getting bound? The index you get in TreeView.bindItem is the linear index it appears in the tree view.

So imagine the following data:

- Root1 (0)
	- Child1 (1)
	- Child2 (2)
	- Child3 (3)
- Root2 (4)
	- Child1 (5)
	- Child2 (6)
	- Child3 (7)

I’ve added the indexes that Unity’s tree view supplies in .bindItem callback for each entry. When your own data is in a tree-like fashion, then you potentially need to calculate the actual data index from the supplied index.

So if you have containers with items, then you will have to convert that index into the respective container, then its respective item.

1 Like