Button.Clicked only working sometimes....?

I have a UIDocument that tracks the current layer on the right side of the layout as
1 - 2 - 3
4 - 5 - 6
7 - 8 - 9

9925029--1435791--traverse_layers.gif

GIF of UIDocument indicating the Current Layer.

To the left of the Layer Indicators is a column of Value Selectors 1-9.

9925029--1435794--mock-can set values anywhere.gif

GIF of UIDocument “Selected Value” Column 1-9.

Here is a snapshot of my UIDocument tree:

Then I’m setting up my Selected Value columns as an array of Buttons[ ].

   VisualElement _root;
   Label[] _layerNumbers; // the layer indicator Labels
   Label _lblCurSide; // Label displaying the current Side.
   Button[] _selectedValueButtons;
   VisualElement[] _visualElements; // Visual Elements used as containers.
   const int VIELEMENTS = 7;
   // Buttons so the user can select values 1-9

   private void OnEnable()
   {
       _layerNumbers = new Label[g.PSIZE + 1];
       _selectedValueButtons = new Button[g.PSIZE + 1];
       _visualElements = new VisualElement[VIELEMENTS + 1];
       _root = GetComponent<UIDocument>().rootVisualElement;


       /*******************************************************************************
        * I just added this for loop to set the VisualElement's pickingMode = Ignore.
        *******************************************************************************/
       for (int i = 1; i <= VIELEMENTS; i++)
       {
           _visualElements[i] = _root.Q<VisualElement>($"vi{i}");
           _visualElements[i].pickingMode = PickingMode.Ignore;
       }

       for (int i = 1; i <= g.PSIZE; i++)
       {
           _layerNumbers[i] = _root.Q<Label>($"Num{i}");
           _layerNumbers[i].visible = false;
           _selectedValueButtons[i] = _root.Q<Button>($"cmdChoose{i}");
           _selectedValueButtons[i].clicked += createSelectionButtonHandler(_selectedValueButtons[i]);
       }
       _lblCurSide = _root.Q<Label>("lblCurSide");
   }

   private Action createSelectionButtonHandler(Button cmd)
   {
       return handleClick;

       void handleClick()
       {
           int iValue = int.Parse(cmd.name.Substring(cmd.name.Length - 1));
         [I] [B] g.SelectedValue = iValue;[/B][/I]
       }
   }

Note that I cannot handleClick is not executed if I am in Layer 1:

9925029--1435803--Cannot set Values in Layer One.gif

However, if I am in Layer 2 I handlClick is executed (sometimes)

9925029--1435806--Can set values in Layer Two.gif

Sometimes I need to go to Layer 3 and back to 2 for handleClick to fire.

I am not setting my styles in Code, but all my styling is done in my uss, and
I’m Enabling my styles using VisualElement.EnableInClassList():

Here is my Button_Focus class:

.Button_Focus {
    border-left-color: rgb(255, 244, 0);
    border-right-color: rgb(255, 244, 0);
    border-top-color: rgb(255, 244, 0);
    border-bottom-color: rgb(255, 244, 0);
    border-top-width: 15px;
    border-right-width: 15px;
    border-bottom-width: 15px;
    border-left-width: 15px;
    border-top-left-radius: 15px;
    border-top-right-radius: 15px;
    border-bottom-right-radius: 15px;
    border-bottom-left-radius: 15px;
}

And this is my .cs listing that Enables my “Button_Focus” class.

   /// <summary>
   /// highlight currently selected value (for setting of
   /// UserValues and Candidates.) by giving it a thick, yellow
   /// border.
   /// </summary>
   private void highlightSelectedValue(Button cmd)
   {
       int selectedValue = int.Parse(cmd.name.Substring((cmd.name.Length - 1)));
       for (int i = 1; i < g.PSIZE + 1; i++)
       {
           _selectedValueButtons[i].EnableInClassList("Button_Focus", i == selectedValue);
       }
   }

Does anyone have any ideas what I might do differently so my handleClick event can fire regardless
of which layer I’m in?

Thank You,

Rosco-y

Hi Rosco,

Before I go deeper into your code, I quickly noticed a very common error. When assigning the clicked delegate, you’re using the loop variable inside the delegate in question. C# allows that, but in a way that’s kind of broken, that is, the variable will be shared between all the assigned delegates and will have a value of g.PSIZE all the time.

Here’s an example of how you could fix it:

for (int i = 1; i <= g.PSIZE; i++)
{
    _layerNumbers[i] = _root.Q<Label>($"Num{i}");
    _layerNumbers[i].visible = false;
    _selectedValueButtons[i] = _root.Q<Button>($"cmdChoose{i}");
    // Prevent `clicked` from closing on the loop variable
    var j = i;
    _selectedValueButtons[i].clicked += createSelectionButtonHandler(_selectedValueButtons[j]);
}

I hope this helps :slight_smile:

1 Like

Thank You, I’ll give it a try!
:slight_smile: Rosco