I create array:
TextBox[] textarray = new TextBox[100];
Then in cycle set this params, all items array situated in uniformGrid1
textarray[i] = new TextBox();
textarray[i].Height = 30;
textarray[i].Width = 50;
uniformGrid1.Children.Add(textarray[i]);
How create events Click or DoubleClick that all items array?
Sorry my English.
public static void blah()
{
TextBox[] textarray = new TextBox[100];
List<TextBox> textBoxList = new List<TextBox>();
for (int i = 0; i < textarray.Length; i++)
{
textarray[i] = new TextBox();
textarray[i].Height = 30;
textarray[i].Width = 50;
// events registration
textarray[i].Click +=
new EventHandler(TextBoxFromArray_Click);
textarray[i].DoubleClick +=
new EventHandler(TextBoxFromArray_DoubleClick);
}
}
static void TextBoxFromArray_Click(object sender, EventArgs e)
{
// implement Event OnClick Here
}
static void TextBoxFromArray_DoubleClick(object sender, EventArgs e)
{
// implement Event OnDoubleClick Here
}
EDIT:
A better / recommended way of event registration as per #Aaronaugh: advice:
textarray[i].Click += TextBoxFromArray_Click;
textarray[i].DoubleClick += TextBoxFromArray_DoubleClick;
Just add in your click or double click event handler. For example, to trap double click events:
textarray[i] = new TextBox();
textarray[i].Height = 30;
textarray[i].Width = 50;
textarray[i].MouseDoubleClick += this.OnMouseDoubleClick;
uniformGrid1.Children.Add(textarray[i]);
For the above to work, you class will need a method like:
void OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
// Do something
}
Create a click event handler and then use it to subscribe to the click events of your textboxes, like so:
textarray[i].Click += new EventHandler(textbox_Click);
...
void textbox_Click(object sender, EventArgs e)
{
// do something
}
If the actions you want to take are the same for each textbox, then one click handler will suffice.
Related
I have array of buttons, and array of labels:
Label[] labels = new Label[10];
Button[] but = new Button[10];
While clicking the other button I want to dynamically create new button and new label from the array, i also want the but[i] to change the tex of labels[i]:
private void button1_Click(object sender, EventArgs e)
{
labels[i] = new Label();
labels[i].Location = new System.Drawing.Point(0, 15+a);
labels[i].Parent = panel1;
labels[i].Text = "Sample text";
labels[i].Size = new System.Drawing.Size(155, 51);
labels[i].BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
a = labels[i].Height + labels[i].Top;
but[i] = new Button();
but[i].Text = "-";
but[i].Location = new System.Drawing.Point(0, labels[i].Height + labels[i].Top);
but[i].Parent = panel1;
but[i].Size = new System.Drawing.Size(155, 10);
but[i].Click += new System.EventHandler(but_Click);
i++;
}
private void but[i]_Click(object sender, EventArgs e)
{
labels[i].Text = "Changed Text";
}
But apparently I can't put an array in an event handler, how should I do it then?
One way to do this is to make your method return a handler instead of being a handler:
private EventHandler but_Click(int i)
{
return (s, e) => labels[i].Text = "Changed Text";
}
And use it like:
but[i].Click += but_Click(i);
Or do it inline:
but[i].Click += (s, ea) => labels[i].Text = "Changed Text";
What's happening in either of these is some compiler magic to capture the i variable. It's equivalent to this (which is also a valid, if verbose, way to do it):
class MyWrapper {
private int i;
public MyWrapper(int i) {
this.i = i;
}
public void TheHandler(object sender, EventArgs e) {
// TODO: capture the object that owns `labels` also, or this won't work.
labels[i].Text = "Changed Text";
}
}
//call with
but[i].Click += new EventHandler(new MyWrapper(i).TheHandler);
You could add the array index to the button as Tag property, and then pull it back out in but_Click.
So, add
but[i].Tag = i;
to the button creation. And then change the event handler:
private void but_Click(object sender, EventArgs e)
{
int buttonIndex = (int)((Button)sender).Tag;
labels[buttonIndex].Text = "Changed Text";
}
Or put the event handler inline:
but[i].Click += (s,e) => { label[i].Text = "Changed Text"; }
Or another option using the Tag property, add:
but[i].Tag = label[i];
...
private void but_Click(object sender, EventArgs e)
{
Label label = (Label)((Button)sender).Tag;
label.Text = "Changed Text";
}
Advantage of this approach is you're not relying on keeping arrays in synch after the initial creation of the controls.
I guess this is self-explaining:
public void SomeMehthod()
{
Button btn1 = new Button();
Button btn2 = new Button();
Button btn3 = new Button();
// Your button-array
Button[] btns = new Button[]
{
btn1,
btn2,
btn3
};
foreach(Button btn in btns)
{
// For each button setup the same method to fire on click
btn.Click += new EventHandler(ButtonClicked);
}
}
private void ButtonClicked(Object sender, EventArgs e)
{
// This will fire on any button from the array
// You can switch on the name, or location or anything else
switch((sender as Button).Name)
{
case "btn1":
// Do something
break;
case "btn2":
// Do something
break;
case "btn3":
// Do something
break;
}
}
Or if your array is accessible globaly:
Button[] btns = new Button[5];
Label[] lbls = new Label[5];
private void ButtonClicked(Object sender, EventArgs e)
{
Button clicked = sender as Button;
int indexOfButton = btns.ToList().IndexOf(clicked);
// ..IndexOf() returns -1 if nothign is found
if(indexOfButton > 0)
{
lbls[indexOfButton].DoWhatYouWant...
}
}
I'd like to distinguish each of the Event handler.
(I have only one in my code below. I mean dynamic handler will be the best but, any kind of workarounds will be fine too.)
Please help me.
Thanks !
List<Button> VuttonList = new List<Button>();
private void Form1_Load(object sender, EventArgs e)
{
Button Vutton;
int Kount = 10;
for (int i = 0; i < Kount ; i++)
{
Vutton = new Button();
Vutton.Text = ( i + 1 ).ToString() ;
Vutton.Location = new Point(10, 24 * ( i + 1 ) );
Controls.Add( Vutton );
Vutton.Click += new EventHandler(Kommon);
VuttonList.Add( Vutton );
}
}
private void Kommon(object sender, EventArgs e)
{
MessageBox.Show( sender.ToString() );
}
One event handler is enough, you can cast the sender to Button and this way you know which button has been clicked. Also you can set Name property of buttons when you create them or assign Tag property of them and use it later.
for (int i = 0; i < Kount ; i++)
{
Vutton = new Button();
//...set properties
//Also add Name:
Vutton.Name = string.Format("Vutton{0}", i);
//Also you can add Tag
Vutton.Tag = i;
Controls.Add( Vutton );
Vutton.Click += new EventHandler(Kommon);
//... other stuff
}
Then you can use properties of button this way:
private void Kommon(object sender, EventArgs e)
{
var button = sender as Button;
//You can use button.Name or (int)button.Tag and ...
MessageBox.Show(button.Name);
}
Also to layout your buttons, you can use a FlowLayoutPanel or a TableLayoutPanel.
I am writing a simple calculator script for my C# programming class. It will of course have buttons 0-9 that will update the output textbox to add the number of whatever button is clicked. My problem right now that is I would rather not have to have 10 different click events in my script. I would rather have a loop that cycles through the buttons that will add the same click event to each one and then decide what number to add to the output based on the button.
So right now, I have a click event for the "1" button which is this...
private void btnNum1_Click(object sender, EventArgs e)
{
txtOutput.Text = Convert.ToString(txtOutput.Text + "1");
}
This works fine, but, again, I would rather not have to do this 10 times. How can I create a loop that prevents this?
The button names are btnNum1, btnNum2, btnNum3, etc.
Assuming the button text is just "1", "2" etc you could do this:
private void btnNum_Click(object sender, EventArgs e)
{
var button = sender as Button
txtOutput.Text += button.Content.ToString();
}
Then just apply this event to all the buttons.
Also note you don't need Convert.ToString() as what you are trying to convert is already a string. Using += also cleans up your code a bit.
You could do this to wire-up all of the events in one go:
for (var n = 0; n <= 9; n++)
{
var btn =
this
.Controls
.Find("btnNum" + n.ToString(), false)
.Cast<Button>()
.First();
var digit = n;
btn.Click += (s, e) =>
{
txtOutput.Text = digit.ToString();
};
}
You could enumerate the children controls of your Form/Control, look the type of controls which are type of Button and the name StartWith 'btnNum', with each of these buttons, add a Click event address to btnNum_Click().
Say if all your buttons are contained in a Panel named 'pnlButtons', you could loop all the children like this.
foreach (var control in pnlButtons.Controls)
{
if(control.GetType() == typeof(Button))
{
var button = control as Button;
if (button .Name.StartWith('btnNum'))
{
button.Click += btnNum_Click;
}
}
}
You can use the "Tag" property of the Button control and make an array of Buttons to subscribe to the same event. See sample below:
void InitializeButtons()
{
Button btnNum1 = new Button();
btnNum1.Text = "1";
btnNum1.Tag = 1;
//Button 2..8 goes here
Button btnNum9 = new Button();
btnNum9.Text = "9";
btnNum9.Tag = 9;
Button[] buttons = new Button[]{
btnNum1, btnNum2, btnNum3, btnNum4, btnNum5, btnNum6, btnNum7, btnNum8, btnNum9
};
for (int i = 0; i < buttons.Length; i++)
{
buttons[i].Click += Button_Click;
}
}
void Button_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
int value = (int)button.Tag;
//Do something with value
}
Assuming WinForms, you can recursively search for buttons that start with "btnNum" and wire them up to a common handler like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += Form1_Load;
}
void Form1_Load(object sender, EventArgs e)
{
FindButtons(this);
}
private void FindButtons(Control ctl)
{
foreach(Control ctrl in ctl.Controls)
{
if (ctrl.Name.StartsWith("btnNum") && (ctrl is Button))
{
Button btn = (Button)ctrl;
btn.Click += btn_Click;
}
else if(ctrl.HasChildren)
{
FindButtons(ctrl);
}
}
}
private void btn_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
txtOutput.Text = Convert.ToString(txtOutput.Text + btn.Text);
}
}
I have tried creating textboxes dynamically using lists. All i need now is, how can i reset all text boxes that i have created by hitting a reset button.
The following is my code:
public void button2_Click_1(object sender, EventArgs e)
{
int number = Convert.ToInt32(textBox2.Text);
List<TextBox> inputTextBoxes;
inputTextBoxes = new List<TextBox>();
for (int i = 1; i <= number; i++)
{
Label labelInput = new Label();
TextBox textBoxNewInput = new TextBox();
labelInput.Text = "Activity No: " + i;
labelInput.Location = new System.Drawing.Point(30, textBox2.Bottom + (i * 40));
labelInput.AutoSize = true;
textBoxNewInput.Location = new System.Drawing.Point(labelInput.Width+60, labelInput.Top - 3);
inputTextBoxes.Add(textBoxNewInput);
this.Controls.Add(labelInput);
this.Controls.Add(textBoxNewInput);
}
}
The answer is:
private void resetButton_Click(object sender,EventArgs e)
{
for (int i = 0; i <= inputTextBoxes.Length; i++)
{
inputTextBoxes[i].Text = "";
}
}
And you should declare inputTextBoxes is a class member which is same class' of buttons.
Move the following line outside the event handler function (outside the function but inside the class)
List<TextBox> inputTextBoxes;
Then on the reset button click
private void btnReset_Click(object sender, EventArgs e)
{
foreach(TextBox txt in inputTextBoxes)
{
this.Controls.Remove(txt);
}
inputTextBoxes.Clear();
}
Edit: Corrected the class type in foreach loop (from Button to TextBox)
Is it possible to create an array of controls? Is there a way to get the index of a control if more than one of the controls in the array share the same event handler?
This is certainly possible to do. Sharing the event handler is fairly easy to do in this case because the Button which raised the event is sent as part of the event args. It will be the sender value and can be cast back to a Button
Here is some sample code
class Form1 : Form {
private Button[] _buttons;
public Form1(int count) {
_buttons = new Button[count];
for ( int i = 0; i < count; i++ ) {
var b = new Button();
b.Text = "Button" + i.ToString()
b.Click += new EventHandler(OnButtonClick);
_buttons[i] = b;
}
}
private void OnButtonClick(object sender, EventArgs e) {
var whichButton = (Button)sender;
...
}
}
Based on Kevins comment:
foreach(Button b in MyForm.Controls.OfType<Button>())
{
b.Click += Button_Click;
}
void Button_Click(object sender, EventArgs e)
{
Button clickedButton = sender as Button;
}