Sarr Sarr - 3 months ago 8
C# Question

How to make Buttons interactable=false based on the content of some list?

I'm using c# with Unity, though you probably don't need to know Unity to be of help here :). I would really appreciate your advice, as I'm still new into coding.

I have a panel with 8 buttons. Each adds 1 item to the list. But I need to check if player already has that item on his list (it's a string name), and if so, turn the button corresponding to that item to interactable=false.

In other words, if player has that item, I need to make the button which adds that item inactive (so player can't click to add it to the list again).

The items are just string names on the list of items.
Buttons run simple functions: ButtonList.Add("item1"), and so on.

I tried building something like this:

Button Btn_item0 = GameObject.Find ("Btn_item0").GetComponent <Button>();
Button Btn_item1 = GameObject.Find ("Btn_item1").GetComponent <Button>();
Button Btn_item2 = GameObject.Find ("Btn_item2").GetComponent <Button>();
Button Btn_item3 = GameObject.Find ("Btn_item3").GetComponent <Button>();
Button Btn_item4 = GameObject.Find ("Btn_item4").GetComponent <Button>();
Button Btn_item5 = GameObject.Find ("Btn_item5").GetComponent <Button>();
Button Btn_item6 = GameObject.Find ("Btn_item6").GetComponent <Button>();
Button Btn_item7= GameObject.Find ("Btn_item7").GetComponent <Button>();

List<Button> buttonList = new List<Button>() {Btn_item0, Btn_item1, Btn_item2, Btn_item3, Btn_item4, Btn_item5, Btn_item6, Btn_item7};
List<string> itemList = new List<string>() {"item0", "item1", "item2", "item3", "item4", "item5", "item6", "item7"};

foreach (Button button in buttonList) {
foreach (string item in itemList) {
if (itemList.Contains (item))
button.interactable = false;
}
}


But obviously this won't work. How do you do that properly?

Ps. The above makes all buttons inactive, because in foreach loop we created string item which is every position on the list. So item list contains item on every position of the list, thus all buttons turn inactive.

Doc Doc
Answer

Instead of making a list of buttons, why not make a Dictionary of them, with their names as the keys? The base concept is

var buttons = new Dictionary<string, Button> {
    ("item0", Btn_item0),
    ("item1", Btn_item1),
    ("item2", Btn_item2),
    ("item3", Btn_item3),
    ("item4", Btn_item4),
    ("item5", Btn_item5), 
    ("item6", Btn_item6), 
    ("item7", Btn_item7)
};

But you could automate this

var buttons = new Dictionary<string, Button> ();
for (int i = 0; i < 8 /*number of buttons*/; i++) {
    var itemLabel = "item" + i;
    var button = GameObject.Find ("Btn_" + itemLabel).GetComponent ("Button");
    buttons[itemLabel] = button;
}

Now all you need to do is go over every button with its corresponding item, and disable/enable it if its item is in the player's itemList or not

foreach (var labeledButton in buttons) {
    var itemLabel = labeledButton.Key;
    var button = labeledButton.Value;
    button.interactable = !itemList.contains(itemLabel);
}

The full code is:

var buttons = new Dictionary<string, Button>();
for (int i = 0; i < 8 /*number of buttons*/; i++) {
    var itemLabel = "item" + i;
    var button = GameObject.Find ("Btn_" + itemLabel).GetComponent ("Button");
    buttons[itemLabel] = button;
}

var itemList = new List<string>() {"item0", "item1", "item2", "item3", "item4", "item5", "item6", "item7"};

foreach (var labeledButton in buttons) {
    var itemLabel = labeledButton.Key;
    var button = labeledButton.Value;
    button.interactable = !itemList.contains(itemLabel);
}

you could even save buttons into an instance variable, and you'd only have to set it up in initialization.

Comments