With Unity 6 being recently released with its improvements to UI Toolkit, I decided to take the plunge and start learning to use the UI Builder.
I can say one of the issues I am having in general is that Unity 6 is so recently released, most of the information I can find is for older versions and I’m not sure how accurate it is anymore.
I come from a C# with WPF background, so I am trying to work with splitting code from UI as much as possible. As such I am trying to do as much binding I can in the UI Builder and leave as little as possible to be handled by code.
I am running into the following 2 problems:
1.) I can’t seem to bind the items to a ListView or MultiColumnListView using the UI Builder, and have to set the ItemsSource directly in code and then call RefreshItems(). Is there a way to just bind a list to the ListView or MultiColumnListView from within the UI Builder?
2.) BindingPath for the columns in a MultiColumnListView seem to be doing nothing, and for every column, the entire row item is being bound to each column, regardless of the settings I set for the columnb BindingPath, regardless of whether it is a valid field to the list item, an invalid name, or blank. I can make a cell template and bind say a label text to a field I want, but that would mean I need a cell template for every cell, which will be unmanageable with many columns and many lists, especially when I just want basic text displayed for each.
Here is some relevant code:
namespace Assets.Scripts.Menus.ViewModels
{
abstract class ViewModelBase : ScriptableObject, INotifyBindablePropertyChanged
{
public event EventHandler<BindablePropertyChangedEventArgs> propertyChanged;
protected void NotifyChanged([CallerMemberName] string propertyName = "") =>
propertyChanged?.Invoke(this, new BindablePropertyChangedEventArgs(propertyName));
}
}
namespace Assets.Scriptables.Test
{
[Serializable]
public class SourceData
{
public int number;
public string text;
public float fnumber;
public override string ToString() =>
"SouceData ToString: "+text + ", " + number + ", " + fnumber;
}
[CreateAssetMenu]
class TestVm : ViewModelBase
{
public List<SourceData> items = new()
{
new SourceData(){number = 10, fnumber = 5.5f, text = "one"},
new SourceData(){number = 200, fnumber=-1.0f, text = "two"},
new SourceData(){number = -5, fnumber = 3.33333f, text="three"},
new SourceData(){number = 0, fnumber = 0, text="four"},
new SourceData(){number = 3, fnumber = 22.2f, text="five"},
new SourceData(){number = -100, fnumber = 15.75f, text="six"},
new SourceData(){number = 15, fnumber = 193.2f, text="seven"},
new SourceData(){number = 2, fnumber = 1234f, text="eight"},
new SourceData(){number = -1, fnumber = 50000f, text="nine"}
};
}
}
class ListViewTester : MonoBehaviour
{
UIDocument _Doc;
ListView _View;
MultiColumnListView _MCView;
public TestVm vm;
void Start()
{
_Doc = GetComponent<UIDocument>();
_View = _Doc.rootVisualElement.Q<ListView>("listView");
_MCView = _Doc.rootVisualElement.Q<MultiColumnListView>();
Button b = _Doc.rootVisualElement.Q<Button>("ListViewButton");
b.clicked += B_clicked;
b = _Doc.rootVisualElement.Q<Button>("MultiColumnListViewButton");
b.clicked += B_clicked1; ;
}
private void B_clicked1()
{
_MCView.itemsSource = vm.items;
_MCView.RefreshItems();
}
private void B_clicked()
{
_View.itemsSource = vm.items;
_View.RefreshItems();
}
}
The MultiColumnListView in the UI Builder:
And the result:




