Unity Button Delegates (AddListener) - c#

I'm trying to instantie several button using prefab.
But I've got a problem to Delegate variable.
for(int i = 0; i < _partnerList.partner.Count; i++)
{
GameObject _instance_partner_button = Instantiate(_prefab_partner_button);
_instance_partner_button.name = "_button_"+_partnerList.partner[i].partner_name;
_instance_partner_button.transform.SetParent(GameObject.Find("_UI_menu_partner").transform, false);
// Change Value of The Button ----------------------------------------------------------------
Text _instance_partner_button_text = _instance_partner_button.GetComponentInChildren<Text>();
_instance_partner_button_text.text = _partnerList.partner[i].partner_name;
Button _instance_partner_button_button = _instance_partner_button.GetComponent<Button>();
int _tempInt = i;
// Delegate to Another Script ---------------------------------------------------------------
_instance_partner_button_button.onClick.AddListener(() => _scripts_myScripts_ui.AnimationMenuPartner(_tempInt));
// -------------------------------------------------------------------------------------------
}
The function AnimationMenuPartner() just Debug.Log(_tempInt);
No matter which button I press the result is the same.
I'm maybe missing something, as I see in this link it must be working correctly Link
Thanks you for your help.
Edit :
The Another Script with the function AnimationMenuPartner
public void AnimationMenuPartner(int _tempInt)
{
Debug.Log(_tempInt));
}
The log output print : "4"
Which is the length of the list.

Related

Finding the right Button on click in Unity

So the answer might be simple but my brain doesn't want to work correct lol. My code generates button clones out of an JSON array, which works fine, this is the code:
void DrawUI(){
GameObject buttonObj = transform.GetChild (0).gameObject; //Gets button to clone it
GameObject g;
int N = allCars.Length;
for (int i = 0; i < N; i++)
{
g = Instantiate(buttonObj, transform);
g.transform.Find("name").GetComponent<Text>().text = allCars[i].carName;
g.transform.Find("type").GetComponent<Text>().text = allCars[i].type;
g.transform.Find("price").GetComponent<Text>().text = allCars[i].price+ "€";
if(balance < int.Parse(allCars[i].price))
{
g.transform.Find("price").GetComponent<Text>().color = Color.red;
} else if (balance >= int.Parse(allCars[i].price))
{
g.transform.Find("price").GetComponent<Text>().color = new Color32(53, 140, 3, 255);
}
g.GetComponent<Button>().AddEventListener(i, OpenBuyDialog);
itemIndex = i;
}
Destroy(prefab);
And now I have another method which has to do get the informations of the clicked button, thats the code for it:
public void BuyCar()
{
balance -= int.Parse(allCars[itemIndex].price);
popupNotify.OpenNotification();
}
You might already see the problem, in my for-loop I increase my int variable "itemIndex" and in my second method I'll call
balance -= int.Parse(allCars[itemIndex].price);
and the problem is, if I got for example 5 cars in my DB, "itemIndex" has the value "4" in the end and when I click the first button, it doesn't give me the price from the correct car, instead I get the price of the 5th car. I thought about using an ArrayList/List<>. As I said before, I don't get the it to work..
You could add a variable to each button holding its own associated index. Is Button.AddEventListener a custom method? I can't find it in the API docs. What is it doing with its first argument (i in this case)? If you could just access that value for the clicked button, it would solve your problem.
Otherwise, you could try using an anonymous delegate to essentially include the index as part of each listener. For example in the for loop:
int closureIndex = i ; // Avoid closure problems
g.GetComponent<Button>().AddEventListener( i, () => OpenBuyDialog(closureIndex) );
// If using the standard Unity UI.Button function it would be:
// g.GetComponent<Button>().onClick.AddListener( () => OpenBuyDialog(closureIndex) );
Then use that argument for the index in OpenBuyDialog(), e.g.:
public void OpenBuyDialog(int index)
{
BuyCar(index);
}
public void BuyCar(int index)
{
balance -= int.Parse(allCars[index].price);
popupNotify.OpenNotification();
}

C# How to choose button(X) if x = 1 and then it keeps adding?

I'm trying to a do a program which manages tables in a restaurant.
When the button is clicked its supposed to check all the tables which are in an array if their status is clear,then highlight them by using another png.
ATTEMPTED FAILED CODE:
private void tblf_Click(object sender, EventArgs e)
{
for (; z < 9; )
{
"button" + x +.Image = Image.FromFile("C:\\Users\\cents\\Desktop\\programming stuff\\C#\\TABLES\\sprites and shit\\clearHIGH.png");
x += 1;
y += 1;
z += 1;
}
}
Try using Control.ControlCollection.Find
Button button = this.Controls.Find("button"+x, false).Single();
button.Image = Image.FromFile(
"C:\\Users\\cents\\Desktop\\programming stuff\\C#\\TABLES\\sprites and shit\\clearHIGH.png"
);
Instead of having button1, button2 etc as separate variables, have a single variable buttons of type List or Button[]. That way you can access buttons[x] etc.
Credit
goes to Jon skeet. This was the solution after all!

Is it possible to turn a button into a variable?

I have a code in C# with 26 button in it and I want them to all be disabled until the user does something, but I dont want to copy/paste button1.Enable = false; Button2.Enable = false...
So is there a way to do something like this :
for (int i = 1; i < 26; i++)
{
button+i.Enable = false;
}
Thanks for your help.
You probably want to iterate buttons directly.
foreach(var button in this.Controls.OfType<Button>())
{
button.Enable = false;
}
Using either of Controls.Find or Controls.OfType<Button>() only works at run-time. I prefer a statically checkable compile-time approach. Then if you delete a button on the form the code won't compile. Helps give you that type-safe feeling.
I do it this way. Start with a field to hold the buttons in an array:
private Button[] _buttons = null;
Set the array once in your initialization code:
_buttons = new[] { button1, button2, button26 };
Then when you need to do something with the buttons you just do this:
foreach (var button in _buttons)
{
button.Enable = false;
}
You can use Form.Controls.Find()
for (int i = 1; i < 26; i++)
{
this.Controls.Find("button" + i, searchAllChildren: false).Enable = false;
}
The code assumes your buttons are named button1 through button26.
It's not possible directly like you are, but that doesn't make sense anyway.

ProcessBar counter C#

I have a question about the ProcessBar on C#,
How would I add the value of 1 to a label if the method used when passing an item within a list box was successful ?
I have a method like this
private static Form1 f1 = Application.OpenForms["Form1"] as Form1;
public static void GroupList1(processBar bar)
{
f1.listBox1.Items.Add("User1");
bar.Value = 100;
}
public static void GroupList2(processBar bar2)
{
f1.listBox1.Items.Add("User2");
bar.Value = 100;
} // Etc, etc - up to GroupList6
I would also like to have a label that tells me how many user's were successfully added (using the bar), I was thinking of adding a method like this :
if (bar.Value = 100)
{
f1.label1.Text = "" + 1;
}
Inside of my GroupList1/2 method, but the label always appears as the value 1 .
This method within the main form of my code loads a separate label :
for(int i = 0; int i < listBox1.Items.Count; i++)
{
label2.Text = i.ToString();
}
So, I would like label 1 to increase by 1 if the user has been loaded into my list box successfully, how would I do this ?
Obviously this isn't actually the code I'm using within my program, a method is used if the selected index changes (which is why I want to increase by 1, to ensure the user parsed the method successfully), but the question still remains as described, thanks.
I dont quite understand well what are you trying to achieve, but if you only look in increasing the value of such label then you can easily do this by
if (bar.Value = 100)
{
f1.label1.Text = ""+(int.Parse(f1.label1.Text)+1);
}
or even a better way to initialize the string if for some reason the Text of the label is not an integer
if (bar.Value == 100)
{
int value;
if(!int.TryParse(f1.label1.Text,out value))
{
f1.label1.Text = "1";
}
else
{
f1.label1.Text = ""+(value+1);
}
}
but the best way to do this is to keep track of the value in a separate variable and just update the content of the label.
It's a bad idea to store the actual count in the label's Text property, instead, create a variable:
private static int count;
Now, change your code to something like this:
if (bar.Value = 100)
{
// Add 1
count += 1;
// Update the UI
f1.label1.Text = count.ToString();
}

Linking Buttons Together

I am trying to create some kind of linkage between some buttons on the form so that when i click a button it highlights all the previous buttons to it [some kind of volume controller]
Imagine it as a volume controller. All these colored buttons will be gray and what i want to achieve is as you click on a button it colorizes all the buttons before it; However IDK what is the best way to make a behavior like this without involving tons of useless codes...
First you will need to add all the buttons to an array then handle it from there
Code
//Create an array of buttons and hook up the Click event of each of them
private Button[] VolumeButtons { get; set; }
public Main()
{
InitializeComponent();
//Assuming that you have 21 buttons as it appears in your picture...
VolumeButtons = new Button[21];
VolumeButtons[0] = button1;
VolumeButtons[1] = button2;
VolumeButtons[2] = button3;
VolumeButtons[3] = button4;
VolumeButtons[4] = button5;
VolumeButtons[5] = button6;
VolumeButtons[6] = button7;
VolumeButtons[7] = button8;
VolumeButtons[8] = button9;
VolumeButtons[9] = button10;
VolumeButtons[10] = button11;
VolumeButtons[11] = button12;
VolumeButtons[12] = button13;
VolumeButtons[13] = button14;
VolumeButtons[14] = button15;
VolumeButtons[15] = button16;
VolumeButtons[16] = button17;
VolumeButtons[17] = button18;
VolumeButtons[18] = button19;
VolumeButtons[19] = button20;
VolumeButtons[20] = button21;
foreach (var volumeButton in VolumeButtons)
volumeButton.Click += VolumeButton_Click;
}
void VolumeButton_Click(object sender, EventArgs e)
{
//Find the index of the clicked button
int index = Array.FindIndex(VolumeButtons, 0, VolumeButtons.Length, button => button == ((Button)sender));
//Set the color of all the previous buttons to Aqua, and all the forward buttons to gray [ you may play with it to match your colors then ]
for (int i = 0; i < VolumeButtons.Length; i++)
VolumeButtons[i].BackColor = i <= index ? Color.Aqua : Color.Gray;
}
Put the buttons in an array
Create a click event that looks up the index n of the button (sender) in the array and sets the style of each button 0 - n appropriately.
Wire up each button to the click event
Do as much as you can on your own and come back with specific questions as necessary.

Categories