Search Unity

How Can I change the label of an array property with UIElements?

Discussion in 'UI Toolkit' started by melgeorgiou, Jan 25, 2020.

  1. melgeorgiou

    melgeorgiou

    Joined:
    Nov 3, 2012
    Posts:
    772
    Hi,

    I'm attempting to change the label of a programmatically generated property in UIElements. Take the following code snippet:

    Code (CSharp):
    1.  
    2.  
    3. // Create the Serialized Property
    4. var pf = new PropertyField(sp);
    5.  
    6. // Override the label with our own string
    7. pf.label = label;
    8.  
    9. // Add the property field to the visual element
    10. myVisualElement.Add( pf );
    11.  
    12.  
    Setting the label seems to work on any single serialized property except arrays. When the SerializedProperty is an array (with a foldout), the label is always the name of the unity-processed version of the variable name ( example: myString becomes "My String").

    Am I missing anything here?

    Thanks!
     
    Last edited: Jan 25, 2020
  2. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,231
    This looks like a bug. The PropertyField does not use the label property when it binds to arrays (and has to create a Foldout). Would help if you could report it using Help > Report a Bug...

    As a workaround, what you can do is after the Bind() happens, you can find the Label element of the Foldout inside the PropertyField using the query system and change the label then. Just you might need to do this after every value change as well.
     
  3. melgeorgiou

    melgeorgiou

    Joined:
    Nov 3, 2012
    Posts:
    772
    Hi @uDamian,

    Yeah, I thought it might be a bug. No worries, I'll upload a bug report with a small sample project.

    Is it safe for me to assume this will be fixed soon in a Unity update? If so, I can just leave that part of my code for the moment and wait.

    Thanks! :)
     
  4. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,231
  5. melgeorgiou

    melgeorgiou

    Joined:
    Nov 3, 2012
    Posts:
    772
  6. larsolm5853

    larsolm5853

    Joined:
    Oct 24, 2017
    Posts:
    21
    Here is a workaround extension method for VisualElement if you want to use it. It will operate on any BaseField<T>, PropertyField or array bound Foldout and change the label appropriately:

    Code (CSharp):
    1.         public static void SetFieldLabel(this VisualElement field, string label)
    2.         {
    3.             if (field is PropertyField propertyField)
    4.             {
    5.                 propertyField.label = label;
    6.  
    7.                 // if label is being cleared it will be automatically set to the property name on binding so it then needs to be reset
    8.                 // TODO: figure out a better way to do this
    9.  
    10.                 if (string.IsNullOrEmpty(label))
    11.                 {
    12.                     field.schedule.Execute(() =>
    13.                     {
    14.                         propertyField.label = label;
    15.                         var baseField = field.Q(className: BaseField<int>.ussClassName);
    16.                         baseField.SetFieldLabel(label);
    17.                     }).StartingIn(0);
    18.                 }
    19.             }
    20.             else if (field is Foldout foldout)
    21.             {
    22.                 foldout.text = label;
    23.  
    24.                 // clear the binding of the property to the foldout label
    25.                 var foldoutToggle = foldout.Q<Toggle>(className: Foldout.toggleUssClassName);
    26.                 var foldoutLabel = foldoutToggle.Q<Label>(className: Toggle.textUssClassName);
    27.  
    28.                 foldoutLabel.bindingPath = null;
    29.                 foldoutLabel.binding.Release();
    30.             }
    31.             else if (field.GetType().InheritsGeneric(typeof(BaseField<>)))
    32.             {
    33.                 // label is public but this allows access without knowing the generic type of the BaseField
    34.                 field.GetType().GetProperty("label", BindingFlags.Instance | BindingFlags.Public).SetValue(field, label);
    35.             }
    36.         }
     
  7. melgeorgiou

    melgeorgiou

    Joined:
    Nov 3, 2012
    Posts:
    772
    Thanks for sharing! :)