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
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:
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.