Refreshing a custom inspector for a ScriptableObject on value changed

I have a custom inspector script for a scriptable object which holds a few basic values, and a custom serialized dictionary. I have created an editor script for adding/removing values from the dictionary, but I’m encountering an issue where the values don’t appear update when I add/remove from the dictionary. e.g, I press the ‘Add Element’ button and nothing appears to happen, but if I then deselect and reselect the SO it updates and displays that the dictionary has been properly modified. How do I update the GUI while editing it, rather than having to go through the whole deselect/reselect process?

2023-06-17 20-50-12

Here is the script:

[CustomEditor(typeof(AgentDecision))]
public class AgentDecisionInspector : AgentActionInspectorBase
{
    public override VisualElement CreateInspectorGUI()
    {
        AgentActions action = (AgentActions)target;

        if (action.emotionalWeights == null)
        {
            action.emotionalWeights = new EmotionDictionary();
        }

        VisualElement myInspector = new VisualElement();

        Label header = new Label("Decision");
        header.style.unityFontStyleAndWeight = FontStyle.Bold;

        Button addButton = new Button(() => AddNewEmotion(action.emotionalWeights, out action.emotionalWeights));
        addButton.text = "Add Element"; 
        myInspector.Add(header);
        myInspector.Add(NameInput());
        myInspector.Add(GenerateDictionaryUI(action.emotionalWeights, out action.emotionalWeights));
        myInspector.Add(addButton);

        EditorUtility.SetDirty(target);

        return myInspector;
    }
}

[CustomEditor(typeof(AgentActions))]
public abstract class AgentActionInspectorBase : Editor
{
    SerializedProperty nameProperty;

    private void OnEnable()
    {
        nameProperty = serializedObject.FindProperty("Label");
    }


    public VisualElement NameInput ()
    {
        VisualElement element = new VisualElement();
        TextField txtField = new TextField("Enter Name:", 32, false, false, '*');
        txtField.BindProperty(nameProperty);
        element.Add(txtField);
        return element;
    }

    public VisualElement GenerateDictionaryUI (EmotionDictionary dict, out EmotionDictionary outDict)
    {
        AgentActions action = (AgentActions)target;
        VisualElement entries = new VisualElement();
        entries.style.borderTopColor = Color.gray;
        entries.style.borderBottomColor = Color.gray;
        entries.style.borderLeftColor = Color.gray;
        entries.style.borderRightColor = Color.gray;
        entries.style.borderTopWidth = 2;
        entries.style.borderBottomWidth = 2;
        entries.style.borderLeftWidth = 2;
        entries.style.borderRightWidth = 2;

        foreach (KeyValuePair<Emotion, float> element in dict)
        {
            VisualElement box = new VisualElement();
            box.style.borderBottomWidth = 2;
            box.style.borderBottomColor = Color.gray;
            box.style.flexDirection = FlexDirection.Column;
            EnumField label = new EnumField(element.Key);
            Slider slider = new Slider(-1, 1);
            Button removeButton = new Button(
                () => RemoveEmotion(element.Key, action.emotionalWeights, out action.emotionalWeights));
            removeButton.text = "Remove";
            slider.value = element.Value;

            box.Add(label);
            box.Add(slider);
            box.Add(removeButton);
            entries.Add(box);
        }
        outDict = dict;
        return entries;
    }

    public void RemoveEmotion (Emotion key, EmotionDictionary inDict, out EmotionDictionary outDict)
    {
        inDict.Remove(key);
        outDict = inDict;
    }

    public void AddNewEmotion (EmotionDictionary inDict, out EmotionDictionary outDict)
    {
        if (inDict == null)
        {
            inDict = new EmotionDictionary();
        }

        for (int i = 0; i < Enum.GetNames(typeof(Emotion)).Length; i++)
        {
            if (!inDict.ContainsKey((Emotion)i))
            {
                inDict.Add((Emotion)i, 0);
                break;
            }
        }

        outDict = inDict;
    }
}

Short answer: you can use
yourInspectorElement.RegisterCallback<SerializedPropertyChangeEvent>();

Longer version (example): I have a custom graph editor with an inspector view, every time the node selection changes I update the inspector by calling OnNodeSelectionChanged().
There I use RegisterCallback<SerializedPropertyChangeEvent> to register the InspectorCallback() to any Serialized Property value change
Then in the InspectorCallback() function I set the editor dirty, just so I don’t get multiple updates at the same time.

the full context function is below but I use these lines:

 _inspectorView.UnregisterCallback<SerializedPropertyChangeEvent>(InspectorCallback);
 _inspectorView.RegisterCallback<SerializedPropertyChangeEvent>(InspectorCallback);
private void OnNodeSelectionChanged(TE_NodeView nodeView)
    {
        _inspectorView.Clear();
        DestroyImmediate(_nodeInspectorEditor);
        _nodeInspectorEditor = Editor.CreateEditor(nodeView.node);
        InspectorElement insp = new InspectorElement(_nodeInspectorEditor);
        _inspectorView.Add(insp);

        _selectedNodeView = nodeView;

        _inspectorView.UnregisterCallback<SerializedPropertyChangeEvent>(InspectorCallback);
        _inspectorView.RegisterCallback<SerializedPropertyChangeEvent>(InspectorCallback);
    }