Search Unity

Binding the text of a label

Discussion in 'UI Toolkit' started by JurjenBiewenga, Feb 22, 2019.

  1. JurjenBiewenga

    JurjenBiewenga

    Joined:
    Mar 28, 2018
    Posts:
    24
    Hey!

    I figured out how to do data binding to PropertyFields however it does not appear to be possible when you just want to display some dynamic text. Is this currently possible/planned?
     
  2. patrickf

    patrickf

    Unity Technologies

    Joined:
    Oct 24, 2016
    Posts:
    57
    Hi!
    There is no built-in way to do this. You can either use a TextField, make it read-only (
    isReadOnly=true
    ) and use USS to style it as a
    TextElement
    , or you can derive your own class from
    BaseField<string>
     
  3. Erothez

    Erothez

    Joined:
    May 27, 2015
    Posts:
    20
    Using `isReadOnly=true` doesn't seem to be working in 2019.1.4f1?

    Is there a way to set this from UXML as `readonly="true"` like the docs state doesn't seem to work.

    Currently working around it with some USS and other properties (focusable, pickingmode etc.) but feels hacky.

    Edit: Correction, doesn't accept keyboard input, but does allow selection and deletion...
     
    Last edited: May 27, 2019
  4. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,231
    Try "readonly=true" instead?

    FYI, the Label will be bindable in 2019.3.
     
  5. patrickf

    patrickf

    Unity Technologies

    Joined:
    Oct 24, 2016
    Posts:
    57
    From what I see the field was present in 2019.1.0b1

    In C#: ve.isReadOnly=true;
    In UXML <TextField readonly="true" />
     
  6. Erothez

    Erothez

    Joined:
    May 27, 2015
    Posts:
    20
    Yeah, the properties isReadOnly and readonly are there and have some of the associated behaviours but it doesn't fully work.

    - doesn't accept keyboard input, but does allow selection and deletion of content (defeating the purpose of it)
    - doesn't "fade out" in the expected style of IMGUI readonly stuff

    Submitted a bug[1158450], once ripped it out into smaller repro project, not a major issue as can workaround, but weird behaviour means had to turn it off for now.
     
  7. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,536
    Old thread bump, but I grabbed 2019.3 to peek at this. Is there an example of binding somelabel.text to a property? This seems super useful but I'm not clear on the whole binding magic altogether.
     
  8. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,231
    Bindings only work to member variables on Unity Objects, not C# properties. This is a limitation of Unity's serialization system. However, in 2019.3 and above, you can bind a Label to a member variable via the usual bindingPath property on the Label, just like any other field element. It will just be a one-way binding.
     
  9. LaneFox

    LaneFox

    Joined:
    Jun 29, 2011
    Posts:
    7,536
    Works great! Code for reference.

    Code (CSharp):
    1.         private static void ListBindItem(VisualElement element, int navIndex)
    2.         {
    3.             // find the serialized property
    4.             int vaultId = m_indexMap[navIndex];
    5.             Editor ed = Editor.CreateEditor(Vault.Db.Items[vaultId]);
    6.             SerializedObject so = ed.serializedObject;
    7.             SerializedProperty prop = so.FindProperty("Title");
    8.  
    9.             // build a prefix for the number
    10.             ((Label) element.ElementAt(0)).text = navIndex.ToString("0000") + "\t|";
    11.  
    12.             // bind the label to the serialized target target property title
    13.             ((Label) element.ElementAt(1)).BindProperty(prop);
    14.         }
    GIF for results
    ezgif.com-video-to-gif (1).gif
     
    uDamian likes this.
  10. matthew-holtzem

    matthew-holtzem

    Joined:
    Sep 1, 2016
    Posts:
    40
    Is there guidance anywhere on creating your own custom Bindable Visual Elements?
     
  11. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,231
    You just need to inherit from and implement:
    Code (CSharp):
    1. class YouElement : BindableElement, INotifyValueChanged<string>
    where
    string
    can be a different type you want to bind to.
     
  12. matthew-holtzem

    matthew-holtzem

    Joined:
    Sep 1, 2016
    Posts:
    40
    Ah thanks. I did get it to work but it would still be nice to have some example code for this sort of thing as I kinda just had to guess at proper implementations until things worked and I'm not sure I did things correctly
     
  13. larsolm5853

    larsolm5853

    Joined:
    Oct 24, 2017
    Posts:
    21
    Much of what I have learned about UIElements is from examining the reference that Unity graciously put out for us to look at here! This way you can see how they implemented all of their fields to inform how you would go about creating your own.
     
  14. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,231
    Agreed. We're reworking our UIElements docs and should have more samples as well. In the meantime, feel free to ask more questions here. :)
     
    LaneFox likes this.
  15. DevViktoria

    DevViktoria

    Joined:
    Apr 6, 2021
    Posts:
    94
    Actually now the Label is bindeable indeed :)
    See the attached image.
    And the code-behind is:
    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEditor.UIElements;
    3. using UnityEngine;
    4. using UnityEngine.UIElements;
    5.  
    6. public class ScoreCounter : MonoBehaviour {
    7.     [SerializeField]
    8.     private int _currentScore;
    9.     // Start is called before the first frame update
    10.     void Start () {
    11.         _currentScore = 0;
    12.         InvokeRepeating ("IncrementScore", 0.5f, 1);
    13.     }
    14.  
    15.     void Awake () {
    16.         var uiDocument = GetComponent<UIDocument> ();
    17.         SerializedObject so = new SerializedObject (this);
    18.         uiDocument.rootVisualElement.Bind (so);
    19.     }
    20.  
    21.     void IncrementScore () {
    22.         _currentScore += 10;
    23.     }
    24. }
     

    Attached Files:

  16. sevelee

    sevelee

    Joined:
    Apr 5, 2017
    Posts:
    25
    Hi, I tried bind label with GameObject name, it works.
    But I found that if I bind label text with Asset name, It doesn't work.

    Here is my code:
    Code (CSharp):
    1. var m_AssetView = new ScrollView();
    2.             var assets = AssetDatabase.FindAssets("t:Material", new[]
    3.             {
    4.                 "Assets/Materials"
    5.             });
    6.             var assetList = assets.Select(x => AssetDatabase.LoadAssetAtPath<Material>(AssetDatabase.GUIDToAssetPath(x))).ToList();
    7.             foreach (var asset in assetList)
    8.             {
    9.                 SerializedObject matSo = new SerializedObject(asset);
    10.                
    11.                 var label = new Label();
    12.                 label.bindingPath = "m_Name";
    13.                 label.Bind(matSo);
    14.                 var ve = new VisualElement();
    15.                 ve.Add(label);
    16.                 ve.TrackSerializedObjectValue(matSo, o => {Debug.Log(o.targetObject.name);});
    17.                 m_AssetView.Add(ve);
    18.             }