NET 4.5 C# to create a windows form. I want to dynamically create & add buttons & also assign them click events but want them to be dynamically placed in a particular fashion just like the image.
My question is how do I place the buttons dynamically in the above fashion i.e. 4x4 format (4 buttons in a row, 4 columns but unlimited rows). Is it possible to do so in win forms?
Presently I'm trying the below mentioned code but have no clear idea as to how I can place the buttons as shown above.
public Form1()
{
InitializeComponent();
for (int i = 0; i < 5; i++)
{
Button button = new Button();
button.Location = new Point(160, 30 * i + 10);
button.Click += new EventHandler(ButtonClickCommonEvent);
button.Tag = i;
this.Controls.Add(button);
}
}
void ButtonClickCommonEvent(object sender, EventArgs e)
{
Button button = sender as Button;
if (button != null)
{
switch ((int)button.Tag)
{
case 0:
// First Button Clicked
break;
case 1:
// Second Button Clicked
break;
// ...
}
}
}
Please advise solution with codes.
You can use a TableLayoutPanel and create your buttons dynamically and add them to the panel.
For example:
private void Form1_Load(object sender, EventArgs e)
{
var rowCount = 3;
var columnCount = 4;
this.tableLayoutPanel1.ColumnCount = columnCount;
this.tableLayoutPanel1.RowCount = rowCount;
this.tableLayoutPanel1.ColumnStyles.Clear();
this.tableLayoutPanel1.RowStyles.Clear();
for (int i = 0; i < columnCount; i++)
{
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100 / columnCount));
}
for (int i = 0; i < rowCount; i++)
{
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100 / rowCount));
}
for (int i = 0; i < rowCount* columnCount; i++)
{
var b = new Button();
b.Text = (i+1).ToString();
b.Name = string.Format("b_{0}", i + 1);
b.Click += b_Click;
b.Dock = DockStyle.Fill;
this.tableLayoutPanel1.Controls.Add(b);
}
}
void b_Click(object sender, EventArgs e)
{
var b = sender as Button;
if (b != null)
MessageBox.Show(string.Format("{0} Clicked", b.Text));
}
Note:
Using TableLayoutPanel.Controls.Add(control) we can add controls sequentially to the panel.
Using TableLayoutPanel.Controls.Add(control, columnIndex, rowIndex) we can add controls at specific cells.
Related
This question already has answers here:
how to handle programmatically added button events? c#
(6 answers)
Closed 5 years ago.
Im coding in a windowsformapplication, c#
This is what i have done so far
List<Button> list = new List<Button>();
private void Form1_Load(object sender, EventArgs e)
{
for (int j = 0; j <= 13; j++)
{
for (int i = 0; i <= 13; i++)
{
Button ruta = new Button();
ruta.Location = new Point(0+ (i * 50), 0 + (j * 50));
ruta.Size = new Size(50, 50);
ruta.AutoSize = false;
ruta.Text = "";
ruta.TabStop = false;
list.Add(ruta);
this.Controls.Add(ruta);
}
}
}
What I now want is to be able to click on of these buttons and then change the text of a textbox to the index of the pressed button, I'm a real noob when it comes to C# so I have no idea what im doing atm.
What i thought about was something like
private void ruta_click(object sender, EventArgs e)
{
txtBox.text = list.SelectedItemIndex();
}
which obviously wont work since SelectedItemIndex() isnt a real method but just an example.
You should look for the index of sender in your list. The sender will be the button that was clicked, and generally sender will be the control that triggered the event. Also don't forget to add the handler to the button as you do not do taht in your for right now.
private void Form1_Load(object sender, EventArgs e)
{
for (int y = 0; y <= 13; y++)
{
for (int i = 0; i <= 13; i++)
{
Button ruta = new Button();
ruta.Location = new Point(0 + (i * 50), 0 + (y * 50));
ruta.Size = new Size(50, 50);
ruta.AutoSize = false;
ruta.Text = "";
ruta.TabStop = false;
ruta.Click += ruta_click;
list.Add(ruta);
this.Controls.Add(ruta);
}
}
}
private void ruta_click(object sender, EventArgs e)
{
txtBox.Text = list.IndexOf((Button)sender) + "";
}
I have this code when i choose date, creating buttons in the form. I want to show reservation from when button click, but i don't have specific button id what can i do?
public void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
int cleft = 1;
int btnclock = 9;
List<Button> buttons = new List<Button>();
for (int i = 0; i < 15; i++)
{
Button newButton = new Button();
buttons.Add(newButton);
newButton.Top = cleft * 20;
newButton.Left = 100;
cleft = cleft + 1;
newButton.Text = btnclock.ToString();
cleft = cleft + 1;
this.Controls.Add(newButton);
btnclock++;
}
}
OK, if I understand the question (in one point I will be able to actually ASK questions...)
You just want the buttonID? I see you do not have a click event defined, if you define a click event, the "sender" will be your button that you clicked. You can get the ID text etc at that point. I do hope this helps.
Add " newButton.Click += NewButton_Click;"
`
private void NewButton_Click(object sender, EventArgs e)
{
Button ButtonthatwasClicked = (Button)sender;
Console.WriteLine(ButtonthatwasClicked.Name);
Console.WriteLine(ButtonthatwasClicked.Text);
}`
I leave the null checking etc to you.
I have created Label controls dynamically on button click:
protected void createDynamicLabels_Click(object sender, EventArgs e)
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label MyLabel = new Label();
MyLabel.ID = "lb" + i.ToString();
MyLabel.Text = "Labell: " + i.ToString();
MyLabel.Style["Clear"] = "Both";
MyLabel.Style["Float"] = "Left";
MyLabel.Style["margin-left"] = "100px";
Panel1.Controls.Add(MyLabel);
}
}
When I tried to read back fro another button I see Label Control returned null
Label str = (Label)Panel1.FindControl("lb" + i.ToString());
not sure what went wrong here
protected void bReadDynValue_Click(object sender, EventArgs e)
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label str = (Label)Panel1.FindControl("lb" + i.ToString());
lbGetText.Text = str.Text;
}
}
this is the issue of every time page load event. ASP.net fire every time page load event when any button is click.
suppose in this example..
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
createDynamicLabels();
}
private void createDynamicLabels()
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label MyLabel = new Label();
MyLabel.ID = "lb" + i.ToString();
MyLabel.Text = "Labell: " + i.ToString();
MyLabel.Style["Clear"] = "Both";
MyLabel.Style["Float"] = "Left";
MyLabel.Style["margin-left"] = "100px";
Panel1.Controls.Add(MyLabel);
}
}
protected void bReadDynValue_Click(object sender, EventArgs e)
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label str = (Label)Panel1.FindControl("lb" + i.ToString());
lbGetText.Text = str.Text;
}
}
when Button trigger Page doesn't have any label because it is made on runtime. and Page doesn't find particular label. if you tried above code it is run properly.
protected void Page_Load(object sender, EventArgs e)
{
createDynamicLabels();
}
private void createDynamicLabels()
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label MyLabel = new Label();
MyLabel.ID = "lb" + i.ToString();
MyLabel.Text = "Labell: " + i.ToString();
MyLabel.Style["Clear"] = "Both";
MyLabel.Style["Float"] = "Left";
MyLabel.Style["margin-left"] = "100px";
Panel1.Controls.Add(MyLabel);
}
}
protected void bReadDynValue_Click(object sender, EventArgs e)
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label str = (Label)Panel1.FindControl("lb" + i.ToString());
lbGetText.Text = str.Text;
}
}
in this Example code find label every time because every time it can make labels for this page.
Dynamically created labels exists only until the next postback occurs. When you click on another button to retrieve their values a postback occurs and values become null.
For saving labels state after postback you have to use some hidden field.
If the text / value of the labes does not change it is enough to generate them on every postback (as mck already mentioned). If you need to retrieve changes made on the client side, you should create the controls in the OnInit event instead of the PageLoad and use inputs / texboxes instead of labels.
Another option (which I would recommend) would be to use a asp:Repeater to generate the Labels.
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*/ };
}