I have a Button array in C# WFA and I want to create an event for a click of any button in the array.
How can I do it?
And how to know which location in the array it is?
I know sender is the button itself
You can use a for loop that closes over a variable containing the current index:
for(int i = 0; i < buttons.Length; i++)
{
//it's important to have this; closing over the loop variable would be bad
int index = i;
buttons[i].Click += (sender, args) => SomeMethod(buttons[index], index);
}
You can add the event handler to each button in a for loop.
Inside the handler, you can call array.IndexOf((Button)sender).
try this
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Button[] myButtons = new Button[10];
private void Form1_Load(object sender, EventArgs e)
{
for(int i = 0; i < myButtons.Length; i++)
{
int index = i;
this.myButtons[i] = new Button();
this.myButtons[i].Location = new System.Drawing.Point(((i + 1) * 70), 100 + ((i + 10) * 5));
this.myButtons[i].Name = "button" + (index + 1);
this.myButtons[i].Size = new System.Drawing.Size(70, 23);
this.myButtons[i].TabIndex = i;
this.myButtons[i].Text = "button" + (index + 1);
this.myButtons[i].UseVisualStyleBackColor = true;
this.myButtons[i].Visible = true;
myButtons[i].Click += (sender1, ex) => this.Display(index+1);
this.Controls.Add(myButtons[i]);
}
}
public void Display(int i)
{
MessageBox.Show("Button No " + i);
}
}
}
Related
I'm using this code to create buttons with two lines text
private void button1_Click(object sender, EventArgs e)
{
int top = 50;
int left = 100;
int n = 0;
int s = 99;
for (int i = 0; i < 20; i++)
{
Button button = new Button();
button.Left = left;
button.Top = top;
panel1.Controls.Add(button); // here
button.Size = new Size(50, 50);
if (i == 4 || i == 9||i==14||i==19)
{
top = 30;
left = 23;
top +=button.Top+2;
left += button.Width+2;
}
else
left += button.Width + 2;
n = n + 1;
s = s + 1;
button.Text = Convert.ToString(n) + Environment.NewLine + Convert.ToString(s);
button.Click += Button_Click;
}
}
private void Button_Click(object sender, EventArgs e)
{
string s;
Button button = (Button)sender;
s = button.Text + Environment.NewLine;
MessageBox.Show(s);
}
So I need to select only second line brom my button text when I click dynamic button. How will I do this?
you can store some data in Tag property:
button.Text = Convert.ToString(n) + Environment.NewLine + Convert.ToString(s);
button.Tag = new int[] { n, s };
and later retrive it and use:
private void Button_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
var data = button.Tag as int[];
string s = data[1].ToString();
MessageBox.Show(s);
}
private void Button_Click(object sender, EventArgs e)
{
string s;
Button button = (Button)sender;
s = button.Text + Environment.NewLine;
MessageBox.Show(button.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None)[1]);
}
I don't get any errors from Visual Studio so I assumed that the code was right. When I run the code, I press the button (button1), but nothing happens.
private void button1_Click(object sender, EventArgs e)
{
int a = 0;
int b = 1;
int c = 1;
listBox1.Text += a.ToString();
listBox1.Text += b.ToString();
for (int i = 0; i < 20; i++)
{
c = b;
b = a + b;
a = c;
listBox1.Text += b.ToString();
}
}
Listbox's Text property won't work in this case, since it is used only to set or get the selected item in a listbox, add to the itemsource on each number, then it will work
private void button1_Click(object sender, EventArgs e)
{
int a = 0;
int b = 1;
int c = 1;
StringBuilder finalstring = new StringBuilder();
listBox1.Text += a.ToString();
listBox1.Text += b.ToString();
for (int i = 0; i < 20; i++)
{
c = b;
b = a + b;
a = c;
listBox1.Items.Add(b);
}
}
Does button have button1_Click registered as an event?
You can do it via your code by adding button1.Click += button1_Click, or double clicking it in your form designer.
If this still does not work, put a breakpoint on the code to see if it is executed.
I need to make a ListBox that displays how often a Button is clicked.
The user chooses how many buttons are available to click. Here is what I've tried:
int clicked;
clicked = int.Parse(((Button)(sender)).Text);
freq_array[clicked]++;
for (int i = 0; i < freq_array[clicked]; i++)
lstFrequencies.Items[clicked] = clicked + "\t\t" + freq_array[clicked];
freq_array uses the 'clicked' variable to add to the frequency that button has been clicked. Or, it's supposed to.
When I debug it, 'clicked' always comes out to 0. I want 'clicked' to equal the text value of the button that's clicked. When I try to run the program, I get an error saying "Input string was not in correct format."
Edit:
I was able to fix my program with help from you guys. I realized I didn't show enough of my code to be clear enough, and I apologize for that. I had to add some things and move things around and got it soon enough. Thank you all.
Here is the code just for those who may need help in the future:
public partial class Form1 : Form
{
int[] freq_array = new int[11];
int[] numList = new int[11];
int oBase = 0;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
invisiblity();
}
private void invisiblity()
{
foreach (Control ctrl in this.Controls)
{
if (ctrl is Button)
if (Char.IsDigit(ctrl.Text[0]))
ctrl.Visible = false;
}
}
private void btnSetBase_Click(object sender, EventArgs e)
{
Form2 frmDialog = new Form2();
frmDialog.ShowDialog(this);
if (frmDialog.DialogResult == DialogResult.OK)
{
oBase = frmDialog.Base;
//lblOutDigits.Text = oBase.ToString();
for (int i = 0; i < oBase; i++)
{
numList[i] = i;
}
}
ShowBaseButtons(oBase);
}
private void ShowBaseButtons(int last_digit)
{
invisiblity();
foreach (Control ctrl in this.Controls)
{
if (ctrl is Button)
if (Char.IsDigit(ctrl.Text[0]))
if (int.Parse(ctrl.Text) <= last_digit - 1)
ctrl.Visible = true;
}
}
private void btnN_Click(object sender, EventArgs e)
{
lblOutDigits.Text += ((Button)(sender)).Text;
int clicked = int.Parse(((Button)(sender)).Text);
freq_array[clicked]++;
}
private void btnShowFreq_Click(object sender, EventArgs e)
{
lstFrequencies.Items.Clear();
for (int i = 0; i < oBase; i++)
lstFrequencies.Items.Add(numList[i] + " \t\t\t" + freq_array[i]);
}
Your code should work as long as your Button Text is actually just a number. Since what you are trying to do is create an index, what I usually do is use the Tag Property of the control, set it to the Index I want in the designer and then cast that to an Int.
i.e.
if (int.TryParse(((Button)sender).Tag.ToString(), out clicked))
freq_array[clicked]++;
I believe what is happening is that you are not initializing your ListBox, This example Code does work using your initial method. Just create a new Form and paste it in and test.
public partial class Form1 : Form
{
ListBox lstFrequencies = new ListBox();
int[] freq_array = new int[10];
public Form1()
{
InitializeComponent();
Size = new Size(400, 400);
lstFrequencies.Location = new Point(150, 0);
lstFrequencies.Size = new Size(150, 200);
Controls.Add(lstFrequencies);
int top = 0;
for (int i = 0; i < 10; i++)
{
Button btn = new Button();
btn.Size = new Size(70, 30);
btn.Location = new Point(5, top);
Controls.Add(btn);
top += 35;
btn.Tag = i;
btn.Text = i.ToString();
btn.Click += new EventHandler(btn_Click);
lstFrequencies.Items.Add(i.ToString());
}
}
void btn_Click(object sender, EventArgs e)
{
int clicked;
clicked = int.Parse(((Button)(sender)).Text);
freq_array[clicked]++;
lstFrequencies.Items[clicked] = clicked + "\t\t" + freq_array[clicked]; //Cleaned up you do not need to iterate your list
// Using my example code
//if (int.TryParse(((Button)sender).Tag.ToString(), out clicked))
//{
// freq_array[clicked]++;
// lstFrequencies.Items[clicked] = clicked + "\t\t" + freq_array[clicked];
//}
}
}
Your code always comes out to 0 because you never assign last clicked value to button text. Try this code:
int clicked = 0;
private void button1_Click(object sender, EventArgs e)
{
clicked = Convert.ToInt32(((Button)sender).Text);
lstFrequencies.Items.Add(((Button)sender).Name + " " + ++clicked);
button1.Text = clicked.ToString(); // you lose this line
}
EDIT: Counter from variable member
int clicked = 0;
private void button1_Click(object sender, EventArgs e)
{
// if you want to display button name, change .Text to .Name
lstFrequencies.Items.Add(((Button)sender).Text + " " + ++clicked);
}
Hello I'm currently working on a windows from where I need to be able to add and remove a number of textboxes (and a lable) with a button click.
I have to have it set out within a tableLayoutPanel and Once "Add" is clicked a Label and 5 Text boxes must appear on the same row, and then when I click "Remove" they must dissapear, Hiding won't work as Data needs to be taken from them at a later stage but thats not an issue atm.
The problem is with the removal (I can add them fine as you'll see below) I know whats happening and can guess as to why but I need to find an alternate solution >.<
public partial class Form2 : Form
{
int Count = 1;
int rowIndex = 2, colIndex = 1;
Label Label;
TextBox Value;
TextBox Weight;
TextBox Width;
TextBox Height;
TextBox Length;
private void button1_Click(object sender, EventArgs e)
{
if (Count <= 9)
{
Count += 1;
rowIndex += 1;
tableLayoutPanel10.RowCount = +1;
AddLot(Count);
if (Count > 9)
button1.Enabled = false;
}
button2.Enabled = true;
}
private void button2_Click(object sender, EventArgs e)
{
if (Count == 2)
{
tableLayoutPanel10.Controls.Remove(Label);
tableLayoutPanel10.Controls.Remove(Value);
tableLayoutPanel10.Controls.Remove(Weight);
tableLayoutPanel10.Controls.Remove(Width);
tableLayoutPanel10.Controls.Remove(Height);
tableLayoutPanel10.Controls.Remove(Length);
Count -= 1;
rowIndex -= 1;
button2.Enabled = false;
}
else
{
tableLayoutPanel10.Controls.Remove(Label);
tableLayoutPanel10.Controls.Remove(Value);
tableLayoutPanel10.Controls.Remove(Weight);
tableLayoutPanel10.Controls.Remove(Width);
tableLayoutPanel10.Controls.Remove(Height);
tableLayoutPanel10.Controls.Remove(Length);
Count -= 1;
rowIndex -= 1;
button1.Enabled = true;
}
}
private void AddLot(int Count)
{
Label = new Label();
Label.Dock = DockStyle.Fill;
Label.Text = Count.ToString();
Label.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
Value = new TextBox();
Value.Dock = DockStyle.Fill;
Weight = new TextBox();
Weight.Dock = DockStyle.Fill;
Width = new TextBox();
Width.Dock = DockStyle.Fill;
Height = new TextBox();
Height.Dock = DockStyle.Fill;
Length = new TextBox();
Length.Dock = DockStyle.Fill;
tableLayoutPanel10.Controls.Add(Label, colIndex - 1, rowIndex);
tableLayoutPanel10.Controls.Add(Value, colIndex, rowIndex);
tableLayoutPanel10.Controls.Add(Weight, colIndex + 1, rowIndex);
tableLayoutPanel10.Controls.Add(Width, colIndex + 2, rowIndex);
tableLayoutPanel10.Controls.Add(Height, colIndex + 3, rowIndex);
tableLayoutPanel10.Controls.Add(Length, colIndex + 4, rowIndex);
}
}
All That Happens when I try to remove is the Last added Row of label/textboxes is removed, and then only the rowindex/count decrease on any clocks afterwards.
Any Ideas how to get this to work, I'll accept having to change it almost completely but as I said It must be done in the TableLayoutPanel >.<
Cheers,
Jmaru7
This works 100% for me i spent an hour working on it :
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
tableLayoutPanel1.RowCount = 1;
tableLayoutPanel1.ColumnCount = 6;
removeButton.Enabled = false;
}
private void addButton_Click(object sender, EventArgs e)
{
int index = tableLayoutPanel1.RowCount - 1;
Label label = new Label();
TextBox Value = new TextBox();
TextBox Weight = new TextBox();
TextBox Width = new TextBox();
TextBox Height = new TextBox();
TextBox Length = new TextBox();
label.Dock = DockStyle.Fill;
label.Text = (index + 1).ToString();
label.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
Value.Dock = DockStyle.Fill;
Weight.Dock = DockStyle.Fill;
Width.Dock = DockStyle.Fill;
Height.Dock = DockStyle.Fill;
Length.Dock = DockStyle.Fill;
int i = 0;
tableLayoutPanel1.Controls.Add(label, i++, index);
tableLayoutPanel1.Controls.Add(Value, i++, index);
tableLayoutPanel1.Controls.Add(Weight, i++, index);
tableLayoutPanel1.Controls.Add(Width, i++, index);
tableLayoutPanel1.Controls.Add(Height, i++, index);
tableLayoutPanel1.Controls.Add(Length, i++, index);
tableLayoutPanel1.RowCount += 1;
if (tableLayoutPanel1.RowCount > 9)
{
addButton.Enabled = false;
}
if (tableLayoutPanel1.RowCount > 0)
{
removeButton.Enabled = true;
}
}
private void removeButton_Click(object sender, EventArgs e)
{
if (tableLayoutPanel1.RowCount > 0)
{
int startIndex = ((tableLayoutPanel1.RowCount - 1) * 6) - 1;
for (int i = 0; i < 6; i++)
{
tableLayoutPanel1.Controls.RemoveAt(startIndex--);
}
tableLayoutPanel1.RowCount -= 1;
if (tableLayoutPanel1.RowCount == 0)
{
removeButton.Enabled = false;
}
if (tableLayoutPanel1.RowCount <= 9)
{
addButton.Enabled = true;
}
}
}
}
You are keeping only last added set of controls, you should keep all of them. Now when you delete last added controls, next delete uses reference to already deleted so it wont have any effect.
Best would be to make some storage class for set of the controls and keep them in some kind of collection.
To create Button and its click event in run time I use:
Button b = new Button();
b.Name = "btn1";
b.Click += btn1_Click;
But now I have an array of Buttons to create in run time; how to set each button's event - I cannot interpolate because it's not a string.
Button[] b = new Button(Count);
for (int i=0; i < Count; i++)
{
b[i] = new Button();
b[i].Name = "btn" + i;
b[i].Click += ??????
}
what should I do for "?????"
Option 1:
You can pass an lambda function, and create the handler based on the buttons index in the array like this:
for (int i=0; i < Count; i++)
{
b[i] = new Button();
b[i].Name = "btn" + i;
b[i].Click += (sender, args) =>
{
// your code
}
}
Option 2:
You can pass an anonymus delegate:
b[i].Click += delegate (sender, args) {
// your code
};
Option 3:
You can specify a handler function:
b[i].Click += YourHandlerFunction
// ....
// The handler signature also has to have the correct signature
void YourHandlerFunction(object sender, ButtonEventArgs args)
{
// your code
}
You can bind all buttons to the same event, so put the line like b[i].Click += button_Click;.
Then inside the button_Click event you can differentiate between the buttons, and take the proper actions.
For example:
public void button_Click(object sender, ButtonEventArgs e)
{
if( sender == b[0] )
{
//do what is appropriate for the first button
}
...
}
It depends on what you want to do! If you want to have the same method called for all clicks, do this:
Button[] b = new Button[Count];
for (int i=0; i < Count; i++)
{
b[i] = new Button();
b[i].Name = "btn" + i;
b[i].Click += OnClick
}
private void OnClick(object sender, RoutedEventArgs e)
{
// do something
}
If you want to do something different for each button, e.g. depending on the index, you can do something like this:
Button[] b = new Button[Count];
for (int i=0; i < Count; i++)
{
b[i] = new Button();
b[i].Name = "btn" + i;
b[i].Click += (s, e) => { /*do something*/ };
}