Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Bug Label of a DropdownField sends ChangeEvent

Discussion in 'UI Toolkit' started by jpvanoosten, Nov 20, 2022.

  1. jpvanoosten

    jpvanoosten

    Joined:
    Nov 20, 2009
    Posts:
    42
    I'm trying to implement localization in my game and I have a drop-down field with the different languages that can be selected.

    When the
    DropdownField
    field changes, it sends a
    ChangeEvent<string>
    which I register to update the text of the UI.

    When I update the
    Label
    of the
    DropdownField
    , it also sends a
    ChangeEvent<string>
    using the same callback function!

    I try to filter the event using
    event.target
    , but it's always the
    DropdownField
    and never the
    Label
    .

    Populate the language drop-down with the available languages:
    Code (CSharp):
    1.     IEnumerator Start()
    2.     {
    3.         yield return LocalizationSettings.InitializationOperation;
    4.  
    5.         // Populate the Languages drop-down with the available locales.
    6.         var languages = new List<string>();
    7.         var selected = 0;
    8.         for (int i = 0; i < LocalizationSettings.AvailableLocales.Locales.Count; ++i)
    9.         {
    10.             var locale = LocalizationSettings.AvailableLocales.Locales[i];
    11.             if (LocalizationSettings.SelectedLocale == locale)
    12.                 selected = i;
    13.  
    14.             languages.Add(locale.LocaleName);
    15.         }
    16.  
    17.         // Populate the drop-down menu with the available languages.
    18.         var dropdown = uiDocument.rootVisualElement.Q<DropdownField>("Language");
    19.         dropdown.choices = languages;
    20.         dropdown.value = languages[selected];
    21.     }
    22.  
    Register the value changed event on the language drop-down and query the lable:
    Code (CSharp):
    1.         languageDropdown = menu.rootVisualElement.Q<DropdownField>("Language");
    2.         languageDropdown.RegisterValueChangedCallback(LanguageChanged);
    3.         languageDropdownLabel = languageDropdown.Q<Label>();
    4.  
    Change the locale based on the value in the drop-down:
    Code (CSharp):
    1.     void LanguageChanged(ChangeEvent<string> e)
    2.     {
    3.         // Ignore change events on the label of the drop-down.
    4.         if (e.target == languageDropdownLabel) return; // This doesn't work!!
    5.  
    6.         Debug.Log($"Language changed to: {e.newValue}");
    7.         PlayerPrefs.SetString(LANGUAGE_KEY, e.newValue);
    8.  
    9.         LocalizationSettings.SelectedLocale = LocalizationSettings.AvailableLocales.Locales[languageDropdown.index];
    10.         UpdateLocale();
    11.     }
    12.  
    Update the label text:
    Code (CSharp):
    1.     void UpdateLocale()
    2.     {
    3.         // This also fires the "LaguageChanged" callback function!
    4.         languageDropdownLabel.text = languageString.GetLocalizedString();
    5.         // etc...
    6.     }
    7.  
    So how can I ignore the
    ChangeEvent
    on the Label of the
    DropdownField
    ?
     
  2. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    7,846
    You could try
    languageDropdownLabel.SetValueWithoutNotify(languageString.GetLocalizedString());
     
  3. jpvanoosten

    jpvanoosten

    Joined:
    Nov 20, 2009
    Posts:
    42
    This is not a method on a
    Label
    .
     
  4. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    7,846
    Ah, you need to be explicit with the interface.
    like so

    Code (csharp):
    1. ((INotifyValueChanged<string>)languageDropdownLabel).SetValueWithoutNotify(languageString.GetLocalizedString());
     
  5. jpvanoosten

    jpvanoosten

    Joined:
    Nov 20, 2009
    Posts:
    42
    A bit messy, but it seems to work...

    Thanks @karl_jones
     
    karl_jones likes this.
  6. havchr

    havchr

    Joined:
    Jun 18, 2009
    Posts:
    75
    It feels like there are some slight inconveniences to the api as of current. Why we are unable to filter the change event on label vs. value, is not clear to me. The very verbose cast to make a change in the label text not cascade to a changeEvent in the dropDown, is something I would be hard pressed to figure out without googling into the depths of the forum.

    My expectations of the DropdownField was to be able to do this :
    Code (CSharp):
    1. _dropDownField.RegisterCallback<ChangeEvent<int>>(ev =>
    2.                 {
    3.                    Debug.Log($"We changed {ev.newValue}");
    4.                 });
    5.  
    And get an index into the choices-list of the DropdownField.