ListView makeItem inconsistency

So, I’ve just completed a large refactor for a system I’m working on, and decided to port the editors I’ve built for it over to the new UIElements system.

Since the aim with the editors is to do as little of the serialization and binding directly as possible, I’ve been relying on new PropertyField(...); a lot. In particular, in one place, I’m using it to display an array of a custom class that has a Property Drawer, so that just by creating a property field for the array’s property, everything will display.

For the most part, this is working as intended. Unity is creating a new ListView, populating it with the property drawer, and I’ve even managed to hi-jack the footer add button to let me control some parameters in the new values added.

However, I then thought that it would be nice to add a label before every element, stating its index, and maybe also its exact type. So I attempted the following, where benders is the underlying ListView created by the PropertyField:

Func<VisualElement> lastMakeItem = benders.makeItem;
                benders.makeItem = () =>
                {
                    VisualElement result = lastMakeItem();
                    result.Insert(0, new Label());
                    return result;
                };
                Action<VisualElement, int> lastBindItem = benders.bindItem;
                benders.bindItem = (item, index) =>
                {
                    lastBindItem.Invoke(item, index);
                    ((Label)item[0]).text = "Joint number: " + index;
                    Debug.Log("hi");
                };

And it seems that any attempts at changing makeItem and bindItem, even into completely new functions that don’t try to run the old ones inside of them, are simply ignored. So I’m now left here wondering, is this intended behavior, and I am simply not supposed to set either one of those after the list is populated, or is this just a bug?

For now I can improvise a little to get around this problem, but it makes me worry for the future editors that still need to be ported over.

Unity version - 2021.2.10f1 Personal

ListViews create from a PropertyField use binding in the background, so they create their own makeItem and bindItem later, when binding is resolved. So what you’re seeing (or not seeing in that case) is expected.

To have custom items in a property field, you already have the good solution using Property Drawers. The label could be added from there and bound to an index property.
Otherwise, an option could be to create a custom ListView instead, and have your makeItem create a container for the Label and a PropertyField, that you bind in the bindItem to the data.

I see. It felt a little bit counter-intuitive, but I can understand why it was behaving that way now. I ended up creating a new element type that imitates a ListView to get around this, while also incorporating a way to change the footer and several other things.

Thank you for your answer