Reference a button outside of a loop? - c#

This function dynamically creates nine buttons for use in a game I am making. You can see what attributes I give to the button.
private void createbuttons()
{
int tot = 0;
int x = 100;
int y = 100;
while(tot < 9)
{
string buttonsname = (tot + "button").ToString();
Button creating = new Button();
creating.Name = buttonsname;
creating.Size = new Size(100, 100);
creating.Click += delegate
{
MessageBox.Show("You clicked me!");
};
creating.Text = buttonsname;
if(x > 300)
{
y += 100;
x = 100;
}
creating.Location = new Point(x, y);
Controls.Add(creating);
tot += 1;
x += 100;
}
}
What I want to know is how to reference these buttons in different parts of the same form. Specifically when 'Start Game' is clicked I want to change the text for each button to something different.
private void button10_Click(object sender, EventArgs e)
{
//What would I write here to change the text?
}

You can access the buttons by enumerating the controls, or you could create a list of buttons for future reference, and use that list later.
Here is how you do it with a list:
private IList<Button> addedButtons = new List<Button>();
private void createbuttons() {
int tot = 0;
int x = 100;
int y = 100;
while(tot < 9) {
string buttonsname = (tot + "button").ToString();
Button creating = new Button();
creating.Name = buttonsname;
creating.Size = new Size(100, 100);
creating.Click += delegate {
MessageBox.Show("You clicked me!");
};
creating.Text = buttonsname;
if(x > 300) {
y += 100;
x = 100;
}
creating.Location = new Point(x, y);
addedButtons.Add(creating); // Save the button for future reference
Controls.Add(creating);
tot += 1;
x += 100;
}
}
Now you can do this:
foreach (var btn : addedButtons) {
btn.Text = "Changed "+btn.Text;
}

The form has a property Controls that holds all child controls. To find a child control by its Name property use method Find, which returns the array, because there may be several control with the same Name, but if you make sure that names exist, are unique, and you know their type (Button) you can just take the first item from the array and cast it:
private void button10_Click(object sender, EventArgs e)
{
Button buttonNamedFred = (Button)this.Controls.Find("Fred", false)[0];
buttonNamedFred.Text = "I'm Fred";
}

Related

how to create a list of events for a list of buttons c#?

i have a List of Buttons ... but i want to make an events for each button in the list --i have tried this code
ButtonName.Click += (sender, args) =>
{
Point p = new Point(20 * j, 70);
Product[j].Location = p;
Product[j].Width = 200;
Product[j].Height = 250;
this.Controls.Add(Product[j]);
};
the event i want to make is that when click on any button it should show a List Box which is related to this button.
and every List box have its own data .... the only problem i want to get a solution for it is to make event for every button in list
is that possible ??
Update
for (int j = 0; j < Data.BTN_Name.Count; j++)
{
Category[j].Click += (sender, args) =>
{
Point p = new Point(20 * j, 70);
Product[j].Location = p;
Product[j].Width = 200;
Product[j].Height = 250;
this.Controls.Add(Product[j]);
};
It seems to me that you want to do this:
for (int j = 0; j < Data.BTN_Name.Count; j++)
{
Product[j] = new ListBox()
{
Location = new Point(20 * j, 70),
Width = 200,
Height = 250,
Visible = false,
};
this.Controls.Add(Product[j]);
var captured_j = j;
Category[j].Click += (s, ea) => Product[captured_j].Visible = true;
}
You must capture the j variable to use it in the event handler - hence the code var captured_j = j; just before the event handler.
As I can see, you are actualy trying to tie a some button to some listbox. As #TheGeneral said, you can use a Tag property of button, but I don't like this approach (although it has the right to be, it is just a matter of habit). Here is my example:
public class YourForm : Form
{
private IDictionary<Button, ListBox> _listboxes = new Dictionary<Button, ListBox>();
// use this if you create a button and listbox simultaneously
protected void CreateButtonAndList()
{
var listbox = new ListBox();
// initialize listbox as needed
var button = new Button();
// initialize button as needed
button.Click += ButtonClickHandler;
_listboxes.Add(button, listbox);
}
// use this if you create a button for already existing listbox
protected void CreateButtonFor(ListBox listbox)
{
var button = new Button();
// initialize button as needed
button.Click += ButtonClickHandler;
_listboxes.Add(button, listbox);
}
private void ButtonClickHandler(object sender, EventArgs e)
{
var listbox = _listboxes[sender];
// do what you want with listbox
}
}
Also note, that you probably doesn't need both CreateButtonAndList() and CreateButtonFor() methods. You may leave only one that fit your needs.

How to specify interaction beetween button click event handlers?

In the program, by clicking button2, is created a table and imlemented data insertion. Also created textbox and login button, which is used for reading data from this textbox. When the login button is pressed, next actions should happen:
MessageBox should display some text;
login.Text should be changed;
table, which was created by clicking button2 should be deleted.
I dont know actually how to get access from login.click event handler to table in button2. I guess it should be done somehow by using EventArgs, but i dont understand how. Also I thought about creating some variable outside button2 handler scope, and use it later, but I guess its a bad practise.
Please,tell me how to solve this, or maybe its just wrong decision to create windows forms components such a way? if it`s so, then how to?) here is my code:
private void button2_Click(object sender, EventArgs e)
{
label1.Hide();
label2.Hide();
textBox1.Hide();
textBox2.Hide();
button2.Hide();
int user_count = Int32.Parse(textBox2.Text);
int file_count = Int32.Parse(textBox1.Text);
DataGridView T = new DataGridView();
T.Dock = DockStyle.Top;
T.AutoResizeColumns();
T.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
T.ColumnCount = file_count + 1;
T.RowCount = user_count + 1;
Controls.Add(T);
Controller_cs c = new Controller_cs(user_count, file_count);
for(int i = 1; i < T.RowCount; i++)
{
T.Rows[i].Cells[0].Value = c.user_name_insertion(i-1);
}
for (int i = 1; i < T.ColumnCount; i++)
{
T.Rows[0].Cells[i].Value = c.file_name_insertion(i - 1);
}
for(int i = 1; i < T.RowCount;i++)
{
for(int j = 1; j < T.ColumnCount;j++)
{
T.Rows[i].Cells[j].Value = c.rigts_insertion(j-1,i-1);
}
}
Label l = new Label();
l.Text = "Name";
l.Left = 20;
l.Top = 180;
Controls.Add(l);
TextBox username = new TextBox();
username.Left = 20;
username.Top = 210;
Controls.Add(username);
Button login = new Button();
login.Text = "Enter";
login.Left = 130;
login.Top = 175;
login.Click += login_handler;
Controls.Add(login);
}
private void login_handler(object sender, EventArgs e)
{
Button b = (Button)sender;
if (b.Text == "Enter")
{
b.Text = "Exit";
MessageBox.Show("Enter is done");
}
else
{
b.Text = "Enter";
MessageBox.Show("Quit is done");
}
}

Defining an event handler where the sender was dynamically added [duplicate]

This question already has answers here:
How to add event handler for dynamically created controls at runtime?
(3 answers)
How to add an event to a UserControl in C#?
(6 answers)
Closed 3 years ago.
I am trying to write a C# program that plays checkers. So far I've completed all the "Shallow" things such as generating the board and all the labels etc.
My problem is that all the controls are dynamically added. So I can't just "double click" them and define what to do at Button_Click event.
This is my code for generating the form
public partial class formGameBoard : Form
{
private readonly int m_BoardSize;
private readonly string m_Player1Name;
private readonly string m_Player2Name;
private GameTile m_BlueTile;
private bool m_IsThereBlue;
public formGameBoard(int i_BoardSize, string i_Player1Name, string i_Player2Name)
{
m_BoardSize = i_BoardSize;
m_Player1Name = i_Player1Name;
m_Player2Name = i_Player2Name;
if (m_Player2Name == "(Computer)")
{
m_Player2Name = "Computer";
}
m_IsThereBlue = false;
InitializeComponent();
}
private void formGameBoard_Load(object sender, EventArgs e)
{
int SizeOfButton = 60;
int ButtonRowindex = 0;
int ButtonColindex = 0;
this.Size = new System.Drawing.Size(30 + m_BoardSize * SizeOfButton, 100 + m_BoardSize * SizeOfButton);
Button[,] PlayButtonArray = new Button[m_BoardSize, m_BoardSize];
for (ButtonRowindex = 0; ButtonRowindex < m_BoardSize; ButtonRowindex++)
{
for (ButtonColindex = 0; ButtonColindex < m_BoardSize; ButtonColindex++)
{
PlayButtonArray[ButtonRowindex, ButtonColindex] = new Button();
PlayButtonArray[ButtonRowindex, ButtonColindex].Size = new Size(SizeOfButton, SizeOfButton);
PlayButtonArray[ButtonRowindex, ButtonColindex].Left = 10 + ButtonRowindex * SizeOfButton;
PlayButtonArray[ButtonRowindex, ButtonColindex].Top = 50 + ButtonColindex * SizeOfButton;
if ((ButtonRowindex + ButtonColindex) % 2 == 0)
{
PlayButtonArray[ButtonRowindex, ButtonColindex].Enabled = false;
PlayButtonArray[ButtonRowindex, ButtonColindex].BackColor = Color.Gray;
}
this.Controls.Add(PlayButtonArray[ButtonRowindex, ButtonColindex]);
}
}
FillButtons(PlayButtonArray);
}
public void FillButtons(Button[,] ButtonMatrix)
{
int i, j;
for (i = 0; i < m_BoardSize; i++)
{
for (j = 0; j < m_BoardSize; j++)
{
if ((i + j) % 2 == 1)
{
if (j <= (m_BoardSize / 2) - 2)
{
ButtonMatrix[i, j].Text = "O";
}
if (j > (m_BoardSize / 2))
{
ButtonMatrix[i, j].Text = "X";
}
}
}
}
}
struct GameTile
{
int RowIndex;
int ColumnIndex;
}
}
}
I have no issues with it, it looks very nice in my opinion
My problem is that all those buttons are dynamically added. I didnt drag and drop them. I created them at form load. Now I want something to happen when I click a button. For example, I want the button I clicked to change its color to blue.
How can I do that?
Adding the click event for a button is very simple, like this:
buttonName.Click += (sender, e) => { buttonName.Foreground = Colors.Blue; };
Or if you want to make it a method that will handle many button clicks, you could do this:
buttonName.Click += YourButtonHandler;
private void YourButtonHandler(object sender, EventArgs e)
{
// do something, for example:
Button b = sender as Button;
b.Foreground = Colors.Blue;
}
You can add a handler to Click event of your buttons and use sender parameter.
Also probably the index of button in the array is important for you, so you can store array index of the button in Tag property and use it later.
In the for loop:
var button = PlayButtonArray[ButtonRowindex, ButtonColindex];
button.Tag= new Point(ButtonRowindex, ButtonColindex);
button.Click += Button_Click;
Code for Button_Click:
private void Button_Click(object sender, EventArgs e)
{
var button = sender as Button;
//You can manipulate button here
//Also to extract the button index in array:
var indexes = (Point)button.Tag;
MessageBox.Show(string.Format("This is the button at {0}, {1}", indexes.X, indexes.Y));
}

Array of buttons: change property

I have an array of buttons, like this:
int x = 0, y = 0;
butt2 = new Button[100];
for (int i = 0; i < 100; i++)
{
butt2[i] = new Button();
int names = i;
butt2[i].Name = "b2" + names.ToString();
butt2[i].Location = new Point(525 + (x * 31), 70 + (y * 21));
butt2[i].Visible = true;
butt2[i].Size = new Size(30, 20);
butt2[i].Click += new EventHandler(butt2_2_Click); //problem lies here (1)
this.Controls.Add(butt2[i]);
}
private void butt2_2_Click(object sender, EventArgs e)
{
// want code here
}
I want to change the back color of the button when clicked. I was thinking of passing i to be able to do this:
butt2[i].BackColor = Color.Green;
This should do the trick:
private void butt2_2_Click(object sender, EventArgs e)
{
Button pushedBtn = sender as Button;
if(pushedBtn != null)
{
pushedBtn.BackColor = Color.Green;
}
}
And this holds for most UI events, the 'object sender' parameter refers to the control that 'sent'/'fired' the event.
To learn more about C# event handling, I would start here.
Also, here is a SO question about GUI event handling, answered nicely by Juliet (accepted answer).
Hope this helps.

C# WPF Array of Buttons, Button Coordinates

I'm having a matrix of buttons created in the main grid in a window, and also created the event for each one.
I also have an integer matrix that contains some properties of each button(e.g. int a[1,2] is property for button btn[1,2]).
I am planning to create something like a maze on which you can only pass from one button to another by leaping in the knight(from chess) way.I dont know how to find the coordinates of the button pressed so that I may change the position of the current button.
Button[,] btn = new Button[25, 25];
for (x = 5; x <= n; x++)
{
for (y = 5; y <= n; y++)
{
btn[x, y] = new Button();
left += 72;
btn[x,y].Margin =new Thickness(left,top,0,0);
btn[x,y].Height = 32;
btn[x,y].Width = 32;
btn[x, y].Click += new RoutedEventHandler(btn_Click);
if (a[x, y] == 2)
btn[x,y].Background = Brushes.Red;
else
btn[x,y].Background = Brushes.Blue;
main.Children.Add(btn[x, y]);
}
left = 0;
top += 72;
}
}
private void btn_Click(object sender, RoutedEventArgs e)
{
}
I just go a crazy idea... Why not make your own Button and call it MazeButton, or something?
Derive from Button and add some properties, make use of inheritance.
public class MazeButton : System.Windows.Controls.Button {
private int left;
private int top;
//rest of implementation
}
In that way you can pass the information where the button in your maze resides directly into the button. You can define custom events and anything else you desire.
Try this:
private void btn_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Buttonl;
if(btn!=null)
{
Point renderedLocation = btn.TranslatePoint(new Point(0, 0), this);
}
else
{
//you may throw an exception if you want.
}
}
this is another approch of the problem. I store each button in a List of Tuple instead of a array, then i search wich tuple contains the button with Linq.
This is assuming you are in .NET 4. If not, the class Tuple can be written (you can find it on SO).
private List<Tuple<Button, Int32, Int32>> listButton;
private void SetButtons()
{
// TODO define what is n, left, top
listButton = new List<Tuple<Button, int, int>>();
for (int x = 5; x <= n; x++)
{
for (int y = 5; y <= n; y++)
{
Button btn = new Button();
left += 72;
btn.Margin = new Thickness(left, top, 0, 0);
btn.Height = 32;
btn.Width = 32;
btn.Click += new RoutedEventHandler(btn_Click);
if (a[x, y] == 2)
btn.Background = Brushes.Red;
else
btn.Background = Brushes.Blue;
listButton.Add(new Tuple<Button, int, int>(btn, x, y));
main.Children.Add(btn);
}
left = 0;
top += 72;
}
}
private void btn_Click(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
var tuple = listButton.Where(t => t.Item1 == button).FirstOrDefault();
if (tuple != null)
{
Int32 x = tuple.Item2;
Int32 y = tuple.Item3;
// Do whay you want this x and y found
}
}

Categories

Resources