Adding property field to root after CreateInspectorGUI

While trying to create a custom inspector that only shows certain controls when a key piece of data is not null I ran across this issue. If you attempt to add a PropertyField to your root visual element after the frame that CreateInspectorGUI is called it will not add it properly.

I’ve made a test script that has two buttons. One to add a simple label to the root, and one to add a property field to the root. You will see that the plain label adds fine while the property field seems to not add any of it’s children or not get set up properly.

I’ve attached screenshots of the inspector and the visual debugger after pressing each button a few times.

using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;

[CustomEditor(typeof(AddPropertyFieldBug))]
public class AddPropertyField_Editor : Editor
{
    private VisualElement _root;

    private SerializedProperty _spTestValue;

    private void OnEnable()
    {
        _spTestValue = serializedObject.FindProperty("testValue");
    }
    public override VisualElement CreateInspectorGUI()
    {
        _root = new VisualElement();

        var testValueField = new PropertyField(_spTestValue);
        testValueField.label = "Added On Create";

        var addPropertyFieldButton = new Button(()=>
        {
            _root.Add(new PropertyField(_spTestValue));
        });
        addPropertyFieldButton.Add(new Label("Add Poperty Field"));

        var addLabelFieldButton = new Button(() =>
        {
            _root.Add(new Label("added from button"));
        });
        addLabelFieldButton.Add(new Label("Add Label Field"));

        _root.Add(testValueField);
        _root.Add(addPropertyFieldButton);
        _root.Add(addLabelFieldButton);

        return _root;
    }
}

1 Like

PropertyField generates its internal UI at Bind() time. Bind() can be called on any VisualElement (given the right usings) and will recursively look through all children for elements that have a bindingPath set and bind them to a SerializedObject.

Now, in the Editor and using CreateInspectorGUI, you don’t have to worry about Bind() because the Inspector will call it for you. But it does mean that if you add more elements after the initial CreateInspectorGUI, those elements will remain unbound (and PropertyFields without UI).

To get around this, try this in your Button clicked callback:

_root.Add(new PropertyField(_spTestValue));
_root.Bind(serializedObject);
3 Likes

yup that seems to be working just right. Thanks for the fix :slight_smile:
That will be something nice to cover in documentation whenever that gets another pass. Appreciate the help

2 Likes