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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Get index to remove dynamically added template

Discussion in 'UI Toolkit' started by LordOlives, Nov 30, 2019.

  1. LordOlives

    LordOlives

    Joined:
    Aug 24, 2015
    Posts:
    3
    I'm trying to create a custom inspector that will allow me to add/remove entries dynamically, but i'm having some issues.

    - I have created a UXML that contains a VisualElement which I am using as a placeholder.
    Code (UXML):
    1.  
    2. <Engine:VisualElement name="placeholder-characters">  
    3.         <!-- Character templates will be dynamically added here! -->
    4.     </Engine:VisualElement>
    5.  
    - I have created a second UXML that is being used as a Template that will be added to the placeholder each time the add button is clicked.
    - I have an add button that when clicked will add the Template to the placeholder and this works fine.
    Code (C#):
    1.  
    2. private void addButtonClick()
    3. {
    4.         VisualElement placeholder = uxmlRoot.Q<VisualElement>("placeholder-characters");
    5.         VisualElement template = uxmlTemplateCharacter.CloneTree();
    6.         placeholder.Add(template);
    7.         //... additional code for setting the new template values.
    8. }
    9.  
    - Within the template I have defined a remove button and when clicked I would like to remove the instance for which the button is a part of. I can remove the instance using 'placeholder.RemoveAt(0);' to remove the first instance in the list, but i'm not quite sure how I can get the index value for the instance where the button was clicked.

    Any help will be much appreciated.
     
  2. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,203
    placeholder.IndexOf(button.parent).RemoveFromHierarchy()
    should do it.

    On the button, you can use
    button.clickable.clickedWithEventInfo
    to register a callback that gives you an
    EventBase e
    , where you can get the sender (button) via
    e.target as Button
     
  3. LordOlives

    LordOlives

    Joined:
    Aug 24, 2015
    Posts:
    3
    This doesn't appear to work because of an error:
    Code (csharp):
    1. placeholder.IndexOf(button.parent).RemoveFromHierarchy()
    Error: 'int' does not contain a definition for 'RemoveFromHierarchy' and no accessible extension method 'RemoveFromHierarchy' accepting a first argument of type 'int' could be found (are you missing a using directive or an assemly reference?)

    I changed the addButtonClick method to include:
    Code (csharp):
    1. queryButton = xmlRoot.Query<Button>("button-remove");
    2. queryButton.Last().clickable.clickedWithEventInfo += e => removeButtonClick(e);
    Then I changed the removeButtonClick method to:
    Code (csharp):
    1.  
    2. private object removeButtonClick(EventBase e)
    3. {
    4.     Button clickedButton = e.target as Button;
    5.     VisualElement buttonParent = clickedButton.parent.parent.parent.parent;
    6.     buttonParent.RemoveFromHierarchy();
    7. }
    8.  
    This appears to be working now.
     
  4. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,203
    My bad. Not sure what I was thinking here. Should have just been:
    button.parent.RemoveFromHierarchy()


    That said, if you really need to remove a
    .parent.parent.parent.parent
    , I would recommend instead giving
    VisualElement buttonParent
    in your UXML a name and using a quick while loop to find it:
    Code (CSharp):
    1. var buttonParent = clickedButton.parent;
    2. while (buttonParent != null && buttonParent.name != "correct-parent")
    3. {
    4.     buttonParent = buttonParent.parent;
    5. }
    Something like
    .parent.parent.parent.parent
    is very sensitive to hierarchy changes later on.
     
  5. schirDev

    schirDev

    Joined:
    Mar 7, 2018
    Posts:
    12
    In this example, is there a need to unsubscribe/ unregister the clickable.clicked event before removing the button? I have a similar case and I´m pretty new to EditorScripting
     
  6. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,203
    There is no such need. The garbage collector should take care of cleaning up any lambdas floating around at some point, and in the meantime, your clickable will not be called since the Button cannot be clicked as it's no longer in the hierarchy and visible.