Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question How to identify which element was clicked?

Discussion in 'UI Toolkit' started by Kazko, Jan 15, 2021.

  1. Kazko

    Kazko

    Joined:
    Apr 2, 2014
    Posts:
    82
    I am trying to create a dynamic list of options for runtime menu, but have trouble identifying which of the options was clicked ...

    First I instantiate multiple items and .Add(item) them to some parent VisualElement ...
    then I customize the items (for example change label/icon) ...
    then I register a ClickEvent callback method to each of those items ...

    when I receive the callback, how do I know which one was clicked? Is there some special identifier? I tried googling and reading the manual but couldn't find a straightforward way.

    I managed to make it work by storing a dictionary of item.GetHashCode and a custom string identifier, and looking up the identifier in callback via clickEvent.target.GetHashCode ... but I'm sure I'm missing something and there are actually elegant ways of doing this?

    Thanks for any info!
     
  2. broots

    broots

    Joined:
    Dec 20, 2019
    Posts:
    54
    Heya, I think you're basically on the money here, I use dictionaries and event.currentTarget


    Code (CSharp):
    1.        
    2.  
    3. private readonly Dictionary<VisualElement, Object> itemClickLink =
    4.     new Dictionary<VisualElement, Object>();
    5. //Populate items somehow
    6.  
    7.  private void OnItemClicked(ClickEvent evt)
    8.         {
    9.             if (!(evt.currentTarget is VisualElement ve)
    10.                 || !itemClickLink.TryGetValue(ve, out var obj))
    11.                 return;
    12.  
    13.             if (evt.clickCount == 1) onItemSelected?.Invoke(obj);
    14.         }
    15.  
     
    Kazko likes this.
  3. RKar

    RKar

    Joined:
    Mar 6, 2019
    Posts:
    22
    if you use one callback action for all elements - try this:

    Code (CSharp):
    1. private void Start()
    2.         {
    3.             VisualElement element = new VisualElement();
    4.  
    5.             element.RegisterCallback<ClickEvent>(ev => CallbackMethod(element));
    6.         }
    7.  
    8.         private void CallbackMethod(VisualElement elem)
    9.         {
    10.             //do stuff
    11.         }
     
    naturebalance and Kazko like this.
  4. Kazko

    Kazko

    Joined:
    Apr 2, 2014
    Posts:
    82
    Great! This allows me to use VisualElement.userData! I set the data when creating the element, then read it when the element is passed via callback.

    Also, can anything be done with the closure allocations? Rider suggests that "Closure can be eliminated: Method has overload to avoid closure creation" for RegisterCallback method, but I am unable to find or utilize it.
     
  5. RKar

    RKar

    Joined:
    Mar 6, 2019
    Posts:
    22
    May be ev argument have link to target.