C# How to define event for dynamically created control? - c#

I have written a code that create buttons dynamically. The code works well, and create controls when I click on a button. Now the next task is, I want to define click event for these dynamically created controls. How can I do this ? Below is the code, Please modify this code and paste in a reply, so that I can understand easily.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// create controls dynamically on form
int n = 4;
private void btnDisplay_Click_1(object sender, EventArgs e)
{
Button[] button = new Button[n];
int previousButtonPositionY;
int previousButtonHeight;
for (int i = 0; i < n; i++)
{
button[i] = new Button();
button[i].Name = "btnButton" + i;
button[i].Text = "btnButton" + i;
if (i > 0)
{
previousButtonPositionY = button[i - 1].Location.Y;
previousButtonHeight = button[i - 1].Height;
}
else
{
previousButtonPositionY = 50;
previousButtonHeight = 0;
}
button[i].Location = new Point(0, previousButtonPositionY + previousButtonHeight);
}
for (int i = 0; i < n; i++)
{
panel1.Controls.Add(button[i]);
}
}
}

After you have initialized your button you can add an onclick event to it with
button[i].Click += new EventHandler(button_Click);
More here: http://msdn.microsoft.com/en-us/library/ms743596%28v=vs.110%29.aspx

Related

How can I access to my Grid table from my private method

I started yesterday a new proyect in c# with WPF. My first time with it.
I'm trying to do the tictactoe game with graphical interface so i create the grid and i use bottons to change the state (it's not finish yet).
Here is the declaration of the class:
public partial class juego : Window
{
private juego tab;
public juego( int size)
{
InitializeComponent();
this.tab = CreateDynamicWPFGrid(size);
}
Here is the method that created the grid.
public juego CreateDynamicWPFGrid(int size)
{
Grid DynamicGrid = new Grid();
DynamicGrid.Name = "GridTablero";
DynamicGrid.Width = 400;
DynamicGrid.HorizontalAlignment = HorizontalAlignment.Left;
DynamicGrid.VerticalAlignment = VerticalAlignment.Top;
DynamicGrid.ShowGridLines = true;
DynamicGrid.Background = new SolidColorBrush(Colors.LightSteelBlue);
for (int i = 0; i < size; i++)
{
ColumnDefinition gridCol1 = new ColumnDefinition();
DynamicGrid.ColumnDefinitions.Add(gridCol1);
RowDefinition gridRow1 = new RowDefinition();
gridRow1.Height = new GridLength(45);
DynamicGrid.RowDefinitions.Add(gridRow1);
}
for (int fila = 0; fila < DynamicGrid.RowDefinitions.Count; fila++)
{
for (int columna = 0; columna < DynamicGrid.RowDefinitions.Count; columna++)
{
System.Windows.Controls.Button newBtn = new Button();
newBtn.Content = fila.ToString() + "_" + columna.ToString();
newBtn.Name = "Button" + fila.ToString() + "_" + columna.ToString();
newBtn.SetValue(Grid.ColumnProperty, columna);
newBtn.SetValue(Grid.RowProperty, fila);
newBtn.Click += new RoutedEventHandler(button_Click);
DynamicGrid.Children.Add(newBtn);
}
}
tablero.Content = DynamicGrid;
return tablero;
}
So the thing is that i want to iterate over the grid and then, count the buttons which content means if they are X, O or white.
I tried to use in my private method something like tab.Content but i really don't have any idea.
Anyways, i would like to know if this it is even possible.
After all, i come up with a solution by myselft.
So, i changed some lines in the class.
public partial class juego : Window
{
private ArrayList jugadores;
public juego(ArrayList jugadores, int size)
{
InitializeComponent();
tablero.Content = CreateDynamicWPFGrid(size);
}
Then i changed the return from the CreateDynamicWPFGrid:
return dynamicGrid;
And then, one method that i call when i click on buttons.
Grid boardValidar = tablero.Content as Grid;
Button[,] botones = new Button[boardValidar.ColumnDefinitions.Count, boardValidar.ColumnDefinitions.Count];
var buttons = boardValidar.Children.Cast<Button>();
for (int i = 0; i < boardValidar.ColumnDefinitions.Count; i++)
{
for (int j = 0; j < boardValidar.RowDefinitions.Count; j++)
{
botones[i, j] = buttons.Where(x => Grid.GetRow(x) == j && Grid.GetColumn(x) == i).FirstOrDefault();
}
}
So, i cast the grid and then, i do the same with all the buttons.
After this i use the linq to put in the array and that's all.
I know my code it's no the best but i got what i wanted.

How to expand an group box when an button is clicked

I have an.exe and I need to collapse a group_box when it is not used and want to expand when a button is clicked.
As of now, I have created a group-box and its been disabled and if a button is clicked that will be enabled and now I want to change the current process that is instead of disabling I want to collapse and instead of enabling I want to expand that group_box.
As of now, for the page load:
groupboxname.enabled=false;
Button click:
groupboxname.enabled=true;
You Can Also Try Something Like This For Collapse And Expand The groupbox.
public partial class Form1 : Form
{
int height, width;
bool IsFirstClick = false;
public Form1()
{
InitializeComponent();
height = groupBox1.Height;
width = groupBox1.Width;
groupBox1.Height = 0;
groupBox1.Width = 0;
}
private void button1_Click(object sender, EventArgs e)
{
if (!IsFirstClick)
{
IsFirstClick = true;
groupBox1.Width = width;
for (int i = 0; i < height; i++)
{
groupBox1.Height = i;
}
}
else
{
IsFirstClick = false;
for (int i = height; i>0; i--)
{
groupBox1.Height = i;
}
groupBox1.Width = 0;
}
}
}

Can we use parameter in mouse click event c# [duplicate]

This question already has answers here:
Pass extra parameters to an event handler?
(10 answers)
Closed 2 years ago.
I use the loop for a two dimensions array of buttons. I don't know how to know exactly which buttons in array were clicked or not
Here are my code:
for (int i = 0; i < 100 ; i++)
{
for (int j=0 ; j< 100; i++)
{
arrButton[i, j] = new Button();
arrButton[i,j].Size = new Size(size1button, size1button);
arrButton[i,j].Location = new Point(j*size1button, i*size1button);
arrButton.Click += new EventHandler(arrButton_Click);
}
}
Can I use parameters i, j for mouse click event like:
private void arrButton_Click(object sender, EventArgs e, int i, int j)
{
//my idea : add i, j to another int[,] array to keep track of buttons which were clicked
}
If this exits, how to write it correctly? Or can you recommend or method to know exactly where the button was clicked in array ?
Try this
public class Indeces
{
public int IndexI { get; set; }
public int IndexJ { get; set; }
}
Now in loop set Tag
for (int i = 0; i < 100 ; i++)
{
for (int j=0 ; j< 100; i++)
{
arrButton[i, j] = new Button();
arrButton[i,j].Size = new Size(size1button, size1button);
arrButton[i,j].Location = new Point(j*size1button, i*size1button);
arrButton.Click += new EventHandler(arrButton_Click);
arrButton.Tag = new Indeces {IndexI = i,IndexJ = j};
}
}
Get values from Tag here as
private void arrButton_Click(object sender, EventArgs e)
{
var button = sender as Button;
var indeces = (Indeces) button.Tag;//get indeces here
var i = indeces.IndexI;
var j = indeces.IndexJ;
}
You cannot change the EventHandler signature to include your i and j.
However, you can get that information from what is already passed to the arrButton_Click method. Since you set the location of each button as new Point(j*size1button, i*size1button), you can get each i and j component back by dividing the location of your button by size1button.
To get that location, you can use the sender, which is your Button (a cast is necessary):
private void arrButton_Click(object sender, EventArgs e)
{
Button btnClicked = (Button) sender;
int i = btnClicked.Location.Y / size1button;
int j = btnClicked.Location.X / size1button;
}
Also, the code you're currently using to create the buttons have a couple errors.
First, you're never incrementing j; the second loop does i++.
Second, if you want your buttons to appear, you have to add them to your Form's Controls.
Finally, I don't think you can have 10 000 active buttons on your form, try a lower number, like 25.
So the corrected code would look like:
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
arrButton[i, j] = new Button();
arrButton[i, j].Size = new Size(size1button, size1button);
arrButton[i, j].Location = new Point(j*size1button, i*size1button);
arrButton[i, j].Click += arrButton_Click;
Controls.Add(arrButton[i,j]);
}
}
You can also notice that I removed your declaration of new EventHandler, which was redundant.
If you are only interested in Location then whats wrong with this? -
private void arrButton_Click(object sender, EventArgs e)
{
var button = sender as Button;
//now use button.Location
}
But if you want more data other than just location. Here is an example
Use a custom button class -
public class CustomButton<T> : Button {
public T Data{get;set;}
public CustomButton(T data){
this.Data = data; //i didn't compile it, so data type might mismatch.
}
}
Then use this button class -
for (int i = 0; i < 100 ; i++)
{
for (int j=0 ; j< 100; i++)
{
arrButton[i, j] = new CustomButton<T> (...some data);
arrButton[i,j].Size = new Size(size1button, size1button);
arrButton[i,j].Location = new Point(j*size1button, i*size1button);
arrButton.Click += new EventHandler(arrButton_Click);
}
}
In the event handler Cast to CustomButton and voila, there is your location -
private void arrButton_Click(object sender, EventArgs e)
{
var cButton = sender as CustomButton<T>;
// cButton.Datais your point. Have fun
}
BTW, you cannot change the default signature of event handlers, if you want you have to implement your own event/delegate.

Get text from dynamically created TextBox

I have a button when clicked creates textboxes dynamically:
for (int i = 0; i < length; i++)
{
Name.Add(new TextBox());
System.Drawing.Point locate = new System.Drawing.Point(137, 158 + i * 25);
(Name[i] as TextBox).Location = locate;
(Name[i] as TextBox).Size = new System.Drawing.Size(156, 20);
StartTab.Controls.Add(Name[i] as TextBox);
}
I want to get the text entered in Name[i] convert to a string then set it to labels
You can use Control.ControlCollection.Find.
UPDATED:
TextBox txtName = (TextBox)this.Controls.Find("txtNameOfTextbox", true)[0];
if (txtName != null)
{
return txtName.Text;
}
You don't say what type that Name is, it looks like a list of some sort. Try using a List<TextBox> that way you can just access the TextBox properties directly. Something like this. I am also not sure what Control that StartTab is, so I just used a Panel for this test code. (you should also be aware that Name masks the Form's Name property that is why I changed your list to name)
public partial class Form1 : Form
{
List<TextBox> name = new List<TextBox>();
int length = 5;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < length; i++)
{
name.Add(new TextBox() { Location = new System.Drawing.Point(137, 158 + i * 25),
Size = new System.Drawing.Size(156, 20) });
StartTab.Controls.Add(name[i]);
}
}
private void button2_Click(object sender, EventArgs e)
{
for (int i = 0; i < length; i++)
{
StartTab.Controls.Add(new Label() {Location = new System.Drawing.Point(name[i].Location.X + name[i].Width + 20,
name[i].Location.Y),
Text = name[i].Text,
AutoSize = true });
}
}
}

c# creating dynamic textbox in a second form

I am trying to write a code in order to create dynamic textboxes.
I have Function class and have a second form in my program named ProductForm.cs
What I wanna do is to read some data with a function named GetSpecs in my Function.cs and than inside GetSpecs I want to call a function in another class and send data to my other function under ProductForm.cs class.
I am getting blank form at the end.
a part of my GetSpecs function:
private String GetSpecs(String webData)
{
......
ProductForm form2 = new ProductForm();
form2.CreateTextBox(n);
}
ProductForm.cs
public void CreateTextBox(int i)
{
ProductForm form2 = new ProductForm();
form2.Visible = true;
form2.Activate();
int x = 10;
int y = 10;
int width = 100;
int height = 20;
for (int n = 0; n < i; n++)
{
for (int row = 0; row < 4; row++)
{
String name = "txtBox_" + row.ToString();
TextBox tb = new TextBox();
tb.Name = name;
tb.Location = new Point(x, y);
tb.Height = height;
tb.Width = width + row * 2;
x += 25 + row * 2;
this.Controls.Add(tb);
}
y += 25;
}
}
I get a blank form of ProductForm. Textboxes are not created or I cannot see them.
If I put textbox inside
private void ProductForm_Load(object sender, EventArgs e)
I can see textboxes.
You're creating showing a brand new ProductForm instance (in the form2 variable), then adding controls to this (which is never shown).
You are adding the controls to the current form: this.Controls.Add(tb);, you need to add them to the other form:
form2.Controls.Add(tb);

Categories