Search Unity

Resolved TrackPropertyValue does not invoke callback when property value is changed back to original

Discussion in 'UI Toolkit' started by ph3rin, Mar 25, 2023.

  1. ph3rin

    ph3rin

    Joined:
    Jul 22, 2018
    Posts:
    3
    So I have been relying on TrackPropertyValue in my code, and I found a part of it (bug?) that is quite annoying. Basically, whenever I do TrackPropertyValue on a property with some oldValue, it doesn't fire my callback when the value of the property changes from some newValue back to oldValue.

    For example, in the following code, I have a checkbox that controls a bool serialized property (m_isChecked), and a label that tracks its property value so whenever the checkbox is toggled, it respond to the change by changing its text.

    Code (CSharp):
    1. public class TestEditorWindow : EditorWindow
    2. {
    3.     [SerializeField] private bool m_isChecked;
    4.     private SerializedObject m_serializedObject;
    5.  
    6.     [MenuItem("Test/Window")]
    7.     private static void OpenTestWindow()
    8.     {
    9.         GetWindow<TestEditorWindow>();
    10.     }
    11.  
    12.     private void OnEnable()
    13.     {
    14.         var checkbox = new Toggle("Checkbox");
    15.         var label = new Label();
    16.         rootVisualElement.Add(checkbox);
    17.         rootVisualElement.Add(label);
    18.         m_serializedObject = new SerializedObject(this);
    19.         var checkedProperty = m_serializedObject.FindProperty(nameof(m_isChecked));
    20.         checkbox.BindProperty(checkedProperty);
    21.         label.TrackPropertyValue(checkedProperty, _ => label.text = m_isChecked ? "Checked!" : "Not checked!");
    22.     }
    23.  
    24.     private void OnDisable()
    25.     {
    26.         m_serializedObject?.Dispose();
    27.         m_serializedObject = null;
    28.     }
    29. }
    However, the problem is, if the checkbox is initially unchecked, and I then toggle it twice (unchecked => checked => checked), my callback is only executed on the first toggle, not the second one.

    I currently use a workaround where I untrack and then re-track the property in the callback:

    Code (CSharp):
    1. private void OnEnable()
    2. {
    3.     var checkbox = new Toggle("Checkbox");
    4.     var label = new Label();
    5.     rootVisualElement.Add(checkbox);
    6.     rootVisualElement.Add(label);
    7.     m_serializedObject = new SerializedObject(this);
    8.     var checkedProperty = m_serializedObject.FindProperty(nameof(m_isChecked));
    9.     checkbox.BindProperty(checkedProperty);
    10.     label.TrackPropertyValue(checkedProperty, prop => HandleToggled(label, prop));
    11. }
    12.  
    13. private void HandleToggled(Label label, SerializedProperty serializedProperty)
    14. {
    15.     label.text = m_isChecked ? "Checked!" : "Not checked!";
    16.     label.Unbind();
    17.     label.TrackPropertyValue(serializedProperty, prop => HandleToggled(label, prop));
    18. }
    This seems to work. However, it is less than ideal. Is this how we are supposed to use TrackPropertyValue?

    Unity version:
    2022.1.23f1.git.9844400
    Revision: 2022.1/staging 9636b062134a
    Built: Mon, 07 Nov 2022 15:38:26 GMT
     
    oscarAbraham likes this.
  2. ph3rin

    ph3rin

    Joined:
    Jul 22, 2018
    Posts:
    3
    The issue seems to be fixed in 2022.2. The original code works without using the workaround.

    ----
    2022.2.12f1.112.10540
    Revision: 2022.2/staging 022dac4955a3
    Built: Tue, 14 Mar 2023 09:46:46 GMT
     
    oscarAbraham likes this.