Create button during runtime in C#.net? - c#

I know how to create button during runtime.
Button button1 = new Button();
button1.Location = new Point(20,10);
button1.Text = "Click Me";
// adding to groupBox1
groupBox1.Controls.Add(button1);
But the problem is i want to add multiple buttons like this..
for(int i = 1; i < 30; i++) {
Button button[i] = new Button();
// Button customization here...
...
groupBox1.Controls.Add(button[i]);
}
The code above is false code. How can I make this happen true in C#.net? i want to create multiple buttons with button name, button1, button2, button3, button4, .... button30;

You can't declare extra variables at execution time in C# - but you really don't want to anyway, as you wouldn't be able to access them dynamically afterwards. Just create an array:
// buttons would be declared as Button[] as a member variable
buttons = new Button[30];
for(int i = 0; i < buttons.Length; i++) {
buttons[i] = new Button();
// Button customization here...
...
groupBox1.Controls.Add(buttons[i]);
}
Alternatively, use a List<Button>, which will certainly be more convenient if you don't know how many buttons you need beforehand. (See the obligatory "arrays considered somewhat harmful" blog post.)
Of course, if you don't actually need to get at the buttons later, don't bother assigning them to anything visible outside the loop:
for(int i = 0; i < 30; i++) {
Button button = new Button();
// Button customization here...
...
groupBox1.Controls.Add(button);
}
You need to think about what information you need access to when... and how you want to access it. If you logically have a collection of buttons, you should use a collection type variable (like a list or an array).
Frankly I think it's one of the curses of the VS designers that you end up with horrible names such as "groupBox1" which carry no information beyond what's already in the type declaration, and encourage developers to think of collections of controls via individually-named variables. That's just me being grumpy though :)

Try this
for(int i = 1; i < 30; i++) {
Button button = new Button();
// Button customization here...
button.Name = "Button" + i.ToString();
groupBox1.Controls.Add(button);
}

You seem like you're almost on the right track:
// in form class
Button[] m_newButtons = new Button[30];
// in your trigger function
for(int i = 0; i < 30; ++i)
{
m_newButtons[i] = new Button();
// ...
groupBox1.Controls.Add(m_newButtons[i]);
}
If you try and do this more than once you may have to remove the old buttons from the control before adding the new ones.

buttons = new Button[30];
for(int i = 0; i < buttons.Length; i++) {
buttons[i] = new Button();
groupBox1.Controls.Add(buttons[i]);
}
this code will work but button will be added one over other so set location also
buttons = new Button[30];
for(int i = 0; i < buttons.Length; i++)
{
buttons[i] = new Button();
Point p=new Point(xvalue,yvalue);
buttons[i].Location = p;
groupBox1.Controls.Add(buttons[i]);
}
one thing you want to remember increment the x or y position by which you want to display it

Try this one out, I have just learned it myself:
public partial class Form1 : Form
{
Button[] btn = new Button[12];// <--------<<<Button Array
public Form1()
{
InitializeComponent();
}
private void Form1_Load (object sender, EventArgs e)
{
for (int i = 0; i < 12; i++)
{
btn[i] = new Button ( );
this.flowLayoutPanel1.Controls.Add(btn[i]);
}
}
// double click on the flow layoutPannel initiates this code
private void flowLayoutPanel1_Paint(object sender, PaintEventArgs e)
{
}
}

Related

Easiest way to display 2dimensional array of values on buttons

I am looking for optymalize code with displaying 2dimensional array of values on buttons.
I have created grid of buttons like that:
http://screenshot.sh/m2eZscO4i0fXq
and I am actually displaying values of array on this buttons using this code:
button1.Text = board.gameBoard[0, 0].getValue().ToString();
button2.Text = board.gameBoard[0, 1].getValue().ToString();
button3.Text = board.gameBoard[0, 2].getValue().ToString();
button4.Text = board.gameBoard[0, 3].getValue().ToString();
button5.Text = board.gameBoard[1, 0].getValue().ToString();
...
button15.Text = board.gameBoard[3, 2].getValue().ToString();
button16.Text = board.gameBoard[3, 3].getValue().ToString();
Is there easier way to do that? It's working now (http://screenshot.sh/mMDP9pvcC7WOk), but it isn't the best way to do this thing I think. Can somebody show me how do that better?
You can create your buttons dynamically and during creating put the text what you want to Button.Text.
It will be something like:
// array of your buttons (it's not necessary)
var buttons = new Button[4,4];
void SomeMethod()
{
for(var x = 0; x < 4; x++)
{
for(var y = 0; y < 4; y++)
{
var newButton = new Button();
// put your text into the button
newButton.Text = board.gameBoard[x, y].getValue().ToString();
// set the coordinates for your button
newButton.Location = new Point(someCoordinateX, someCoordinateY);
// store just created button to the array
buttons[x, y] = newButton;
// add just created button to the form
this.Controls.Add(newButton).
}
}
}
then, use this method somewhere on initialization step to create and initialize your buttons. The buttons array could be used lately if you will need to modify your buttons somehow.
Hope it will help.

Create a List of existing Buttons

l've 10 ten button on my forms ( 0 to 9) to simulate a calculator
All my buttons are named like this btnCalc0,btnCalc1,btnCalc2,etc...
I want to create an array or list of these buttons to handle event but it's doesn't work because btnCalc doesnt exist(btnCalc+x).
List<Button> lstBtnCalc = new List<Button>();
for (int x = 0; x < 10; x++)
{
lstBtnCalc.Add(btnCalc+x));
}
private void myClick(object sender, EventArgs e)
{
int index = lstBtnCalc.IndexOf(sender as Button);
}
You could populate your array with a loop (See ASh's answer). However, in doing so, you make the code harder to read. The primary test of good code is readable code, so avoid "clever" solutions and keep it simple. In this case, a simple, easy to read and maintain, way is:
List<Button> lstBtnCalc = new List<Button>
{
btnCalc0, btnCalc1, btnCalc2, btnCalc3, btnCalc4,
btnCalc5, btnCalc6, btnCalc7, btnCalc8, btnCalc9
}
You can use Find method:
List<Button> lstBtnCalc = new List<Button>();
for (int x = 0; x < 10; x++)
{
var buttonName = string.Format("btnCalc{0}",x);
var button = this.Controls.Find(buttonName);
if (button != null)
{
lstBtnCalc.Add(button);
}
}
Try this
public partial class Form1 : Form
{
List<Button> lstBtnCalc = null;
public Form1()
{
InitializeComponent();
lstBtnCalc = new List<Button>() { button1, button2, button3, button4 };
}
}
a bit fluent:
List<Button> lstBtnCalc = this.Controls.OfType<Button>().Where(a => a.Name.StartsWith("btnCacl")).ToList();

how to add for loop control

I try to add check box for loop that when i enter 3 for example in textbox and click the button it automatically add 3 check boxes in the form
i tried this code but only add one check box
private void button1_Click(object sender, EventArgs e)
{
int x = Convert.ToInt32(textBox1.Text);
int m = 1;
for (int i = 0; i < x; i++)
{
CheckBox button2 = new System.Windows.Forms.CheckBox();
button2.Location = new System.Drawing.Point(5, m);
button2.Name = "button2 "+ m.ToString();
button2.Size = new System.Drawing.Size(51, 23);
button2.TabIndex = m;
//button2.UseVisualStyleBackColor = true;
this.Controls.Add(button2);
m++;
}
}
You are setting the location of all three buttons to nearly the same place so they are displayed on top of each other. Try spacing them out a little more.
For example change m++; to m += 40;.
You need to space your buttons out a little. Also, you should give each of your buttons a unique ID.
button2.ID = "Button_" + i;

change local function

I have problem with my C# WinForms project. I have a function that should change the place of buttons if they touch each other. For example, if I have btn1 at oldloction = (4,2) and btn2 at oldlocaction (2,6), then if I will move the buttons and they will touch bt1 new location = (2,6) and bt2 new location = (4,2)
now i did that with 2 buttons and it works.
locationx - means the x location on the button and its orgenize firat place of the location feat to the first buttons[0], the second feat to locationx[1] = buttons[1].location.x;
location - works the same ass locationx but uts the y locaion.
private void myText_MouseUp(object sender, MouseEventArgs e)
{
Point oldlocation = new Point(locationx[0], locationy[0]);
Point oldlocation2 = new Point(locationx[1], locationy[1]);
if (buttons[0].Location.Y == buttons[1].Location.Y)
{
buttons[1].Location = oldlocation;
buttons[0].Location = oldlocation2;
}
}
When I tried to make that as a global function it doesn't work and I don't know why.
This is the code of the global function that doesn't work:
private void myText_MouseUp(object sender, MouseEventArgs e)
{
for (int i = 0; i < counter; i++)
{
Point oldlocation = new Point(locationx[i], locationy[i]);
for (int j = 0; j < counter; j++)
{
if (i != j)
{
Point oldlocation2 = new Point(locationx[j], locationy[j]);
if (buttons[i].Location.Y != buttons[j].Location.Y)
{
buttons[j].Location = oldlocation2;
buttons[i].Location = oldlocation;
}
else if (buttons[i].Location.Y == buttons[j].Location.Y)
{
buttons[j].Location = oldlocation;
buttons[i].Location = oldlocation2;
}
}
}
}
}
Try using the button event for when it is pressed to call the function, rather than creating your own.
If the second function is not part of the control or form containing the buttons, it won't have a way to access the buttons array or locationx and locationy. You may need to pass these values as arguments to your function or ensure that they are provided as members of the class containing the second function. Note that generally a utility function would not take in "sender" and "MouseEventArgs" - pass only the specific data that the utility function needs to do its job.

EventHandlers and the sender

So in my program i created a struct with a button and a number value... like this
struct box
{
public int numberValue;
public Button button;
}
I then made a 2D array of this struct
box[,] boxes = new box[20, 20];
Now what i did was make 400 buttons and assigned them to each index of the array... like this
private void createBoxes()
{
int positionX;
int positionY;
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 20; j++)
{
positionX = 20 + (25 * i);
positionY = 20 + (25 * j);
boxes[i, j].button = new System.Windows.Forms.Button();
boxes[i, j].button.Location = new System.Drawing.Point(positionX,positionY);
boxes[i, j].button.Size = new System.Drawing.Size(25, 25);
this.Controls.Add(boxes[i, j].button);
boxes[i, j].button.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
boxes[i, j].button.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
boxes[i, j].button.Visible = true;
boxes[i, j].button.Name = "button";
boxes[i, j].button.Click += new EventHandler(buttonClick);
}
}
}
Now when i make the event handler i want to send "boxes[i,j]" not just "boxes[i,j].button" is there anyway to do this?
Short of defining your own anonymous event handler, there's an easy way to do what you want:
boxes[i, j].button.Tag = boxes[i, j];
Then later:
private void buttonClick(object sender, EventArgs e)
{
var box = ((Button)sender).Tag as box;
}
This can be solved via an anonymous event handler.
var box = boxes[i, j]; // You must use a new variable within this scope
box.button.Click += (obj, args) => buttonClick(box, args);
This is the quickest solution with the least code. Just be aware that anonymous event handlers are notorious for hidden gotchas, and the need to assign a new box variable is an example. The following code will run, but no matter which button you press, the last-assigned values of i and j would be used within the handler.
boxes[i,j].button.Click += (obj, args) => buttonClick(boxes[i,j], args);
No, this is not possible. The individual button control is the one that raises the event, thus it is the object referenced by the sender parameter. The array that contains the button control is irrelevant.
This behavior is by-design. If you wanted to change a property of the button in response to the user clicking on it, it would be impossible to do unless you knew which individual button was clicked. Having only a reference to the array that contains all of the buttons would not provide sufficient information about the individual button that was clicked.

Categories