Dynamic list of editable instances

Hi everybody, it is my intention to create an EditorWindow which contains a list of elements. Each element corresponds to an instance of a class (with several fields) in a List stored the EditorWindow. I want to be able to modify each field of any element of the list. The list is not static, it can grow.

I know how to:

  • Create a ListView, reusing an UXML asset to create its items with makeItem. This is a read-only solution, I need to edit the fields of the items.
  • Create Template/Instance elements. This is a static solution, I need items to be added afterwards.
  • Add new VisualElements as children. This requires a lot of code that I would love to avoid.

None of such things achieves what I want. So I have several questions:

  • Is there a way to bind the items of the list so I can modify them directly without having to write additional code?
  • Is there a way to bind to the element of a list by its index, in UXML?
  • Is there a way to add new Instance objects by code, that are drawn as the defined Template describes?
  • Is it planned to provide a way to use a Template for ListView items?

I also tried to use PropertyDrawers with PropertyFields and so but I could not make it work and could not find one single example of how to use PropertyDrawers with UIElements in an EditorWindow :frowning:

I assume it’s not possible for now.

ListView and its items are now Bindable (as of 2019.3) to a List or T[ ] array serializable field. But this assumes your data is stored in a Unity Object that can be wrapped in a SerializedObject (that is, this works: new SerializableObject(yourObject)). If you just have a simple C# struct with an array, you will have to write the code to bind the data to the UI yourself.

Sort of. All of this assumes you’re using SerializedObjects (like a GameObject or ScriptableObject). If so, you can use the binding-path attribute in UXML to address a specific item in an array by index. For example, if you had a field like this:

public class MyLight : MonoBehaviour
{
    public List<Color> myColor = new List<Color>();
}

you could write some UXML like this to bind to element 1:

<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
    <uie:PropertyField binding-path="myColor.Array.data[1]" />
</ui:UXML>

Here’s a related post on this:
https://discussions.unity.com/t/752661

If you mean the tag, then the equivalent C# call is just:

var template = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("path/to/your.uxml");
var instance = template.CloneTree();

This should already work. You need to provide a custom PropertyDrawer for your list item type, and you use the bindings system to bind your ListView to an array in an Object.

You can also, in your listView.makeItem callback create a PropertyField element and in your listView.bindItem callback set its bindingPath to the correct array item/index in your array.

Have you looked at:
https://docs.unity3d.com/ScriptReference/PropertyDrawer.html

Thank you for answering uDamian. It would be amazing to be able to do something like this:

<engine:VisualElement>
    <engine:ListView name="list" item-height="20" class="myList" binding-path="m_items" item-template="../../ItemTemplate.uxml"/>
</engine:VisualElement>

So we can forget about property drawers, appending visual trees, by-code configuration, etc.

1 Like

It’s come up before. We need a new binding system anyway for runtime so it’s a capability that might come then (for both binding systems).

1 Like