Binding problems with MultiColumnListView and ListView

I followed an example from Unity Manual on how to bind a list to a listview. But here are my problems:

  • When I moved item creation from UXML to code binding to toggle element no longer works.

  • When I try to follow the same logic when binding property to MultiColumnListView it does not work at all.

I would appreciate any help, especially with the cell binding for MultiColumnListView. I’m testing it in Unity 2022.2

[CreateAssetMenu(menuName = "UIToolkitExamples/GameSwitchList")]
public class GameSwitchListAsset : ScriptableObject
{
    public List<Person> people;

    public void Reset()
    {
        people = new()
        {
            new() { name = "P1", age = 1, graduated = true },
            new() { name = "P2", age = 2, graduated = false },
            new() { name = "P3", age = 3, graduated = true },
        };
    }
}

[Serializable]
public struct Person
{
    public string name;
    public int age;
    public bool graduated;
}

[CustomEditor(typeof(GameSwitchListAsset))]
public class GameSwitchListEditor : Editor
{
    public override VisualElement CreateInspectorGUI()
    {
        var root = new VisualElement();

        var list = CreateList();
        root.Add(list);

        var multiColumnListView = CreateMultiColumnList();
        root.Add(multiColumnListView);

        return root;
    }

    private static ListView CreateList()
    {
        var listView = new ListView();
        listView.showBorder = true;
        listView.reorderable = true;
        listView.showFoldoutHeader = true;
        listView.headerTitle = "People";
        listView.bindingPath = nameof(GameSwitchListAsset.people);
        listView.makeItem = () =>
        {
            var container = new VisualElement();
            container.style.flexDirection = FlexDirection.Row;
            container.Add(new Toggle
            {
                bindingPath = nameof(Person.graduated)
            });
            container.Add(new TextField
            {
                bindingPath = nameof(Person.name)
            });
            container.Add(new IntegerField
            {
                bindingPath = nameof(Person.age)
            });
            return container;
        };
        return listView;
    }

    private  MultiColumnListView CreateMultiColumnList()
    {
        var multiColumnListView = new MultiColumnListView();
        multiColumnListView.showBorder = true;
        multiColumnListView.reorderable = true;
        multiColumnListView.showFoldoutHeader = true;
        multiColumnListView.headerTitle = "People";
        multiColumnListView.bindingPath = nameof(GameSwitchListAsset.people);
        multiColumnListView.columns.Add(new Column
        {
            title = "Enabled",
            stretchable = true,
            makeCell = () => new Toggle
            {
                bindingPath = nameof(Person.graduated)
            }
        });
        multiColumnListView.columns.Add(new Column
        {
            title = "Name",
            stretchable = true,
            makeCell = () => new Label
            {
                bindingPath = nameof(Person.name)
            }
        });
        return multiColumnListView;
    }
}

ListView will search for a single BindableElement in the binding phase and bind everything under it, so you’ll need to change your container for a BindableElement in order for all the hierarchy to be bound.

As for multi column controls, I’m afraid they don’t support editor bindings out of the box unfortunately, because the wrapper container is not bindable. They probably shouldn’t be BindableElements at the moment. I’ll make a note with the team so that we look into this. Thanks for reporting !
As a workaround, you can bind every cell individually with the relative property, during bindCell.