How do I create a C# Array of Buttons? - c#

How do I build an array of buttons in a Winforms application?
What I am trying to do is this: I have a lot of buttons in a sort of calendar arrangement, that are indicating time slots. IE: Monday0700Button, Monday0730Button, Monday0800Button, and so on in 30min intervals.
I have a xml database, where one of the fields for appointments is <Duration> When the duration = 0.5hrs, and the <Time> field equals "07:00am", to color the 'Monday0700Button'. When the Duration is 1.0hrs, I want it to populate 'Monday0700Button' as well as the following time slot button of 'Monday0730Button'.
Any ideas?
Thanks.

Yes, you can build a list of buttons like below.
List<Button> listOfButtons = new List<Button>();
listOfButtons.Add(yourButton);

Yes, it's no problem to build an array of Buttons, or any object.
You won't be able to see them in the Visual studio designer, but they'll work just fine.
A long time ago I used a 2-D array of buttons to build the UI for an calculator app. I had used an HP-15C for a long time, and missed it.
The array approach worked fine.
Button[] numberButtons=new Button[] { btn0, btn1, btn2, btn3, btn4, btn5, btn6, btn7, btn8, btn9, btnDecimalPt};
Button[] operationButtons=new Button[] { btnDiv, btnMult, btnSubtract, btnAdd };
foreach (var b in numberButtons)
b.Click += new System.EventHandler(this.Number_Click);
foreach (var b in operationButtons)
b.Click += new System.EventHandler(this.Operation_Click);
// etc
Button[][] allButtons=
{
new Button[] {btnSqrt, btnExp, btn10x, btnPow,btnMultInverse, btnCHS, null, null, null, null},
new Button[] {btnN, btnInterest, btnPMT, btnPV, btnFV, null, btn7, btn8, btn9, btnDiv},
new Button[] {btnLn, btnLog, btnSine, btnCosine, btnTangent, btnPi, btn4, btn5, btn6, btnMult},
new Button[] {btnRoll, btnSwap, btnCLRfin, btnCLX, btnCLR, btnEnter, btn1, btn2, btn3, btnSubtract},
new Button[] {btnInt, btnFrac, btnFix, btnStore, btnRecall, null, btn0, btnDecimalPt, btnNotUsed, btnAdd}
};
// programmatically set the location
int col,row;
for(row=0; row < allButtons.Length; row++)
{
Button[] ButtonCol= allButtons[row];
for (col=0; col < ButtonCol.Length; col++)
{
if (ButtonCol[col]!=null)
{
ButtonCol[col].TabIndex = col + (row * allButtons.Length) +1;
ButtonCol[col].Font = font1;
ButtonCol[col].BackColor = System.Drawing.SystemColors.ControlDark;
ButtonCol[col].Size=new System.Drawing.Size(stdButtonWidth, stdButtonHeight);
ButtonCol[col].Location=new Point(startX + (col * stdButtonWidth),
startY + (row * stdButtonHeight) ) ;
}
}
}

Yep, definitely possible, but probably unnecessary.
If I understand you correctly, you should be able to add a FlowLayoutPanel to your Form and then loop through your XML, instantiating a new Button, as necessary. Wire up the event handler for the Click event, then add the button to the FlowLayoutPanel by calling the Add() method off of the Controls property on your FlowLayoutPanel.
while (reader.Reader())
{
// Parse XML here
// Instantiate a new button that will be added to your FlowLayoutPanel
Button btn = new Button();
// Set button properties, as necessary
btn.Text = "Foo";
btn.Click += new EventHandler(SomeButton_Click);
// Add the button to the FlowLayoutPanel
flowLayoutPanel.Controls.Add(btn);
}
While a FlowLayoutPanel makes it easy to do the layout for your buttons, it might not work for you. If that's the case, you will have to work out the X and Y coordinates for your buttons as you loop through the XML.
One problem that you will encounter with the above approach is that it always calls the exact same event handler. As a result, you will have to come up with a way to determine which button has been clicked. One approach might be to extend the Button control to provide additional properties that can be used to acknowledge the time period.

Buttons, like all GUI elements, are objects just like any other (that also happen to be displayable). So yes, you can have arrays, lists, dictionaries - whatever you want containing buttons. Taylor L's response has some sample code.

Yes, this is possible, as Taylor L demonstrated. The only catch is that VB6-style control arrays, created by copying and pasting the control, can no longer be done in the forms editor.

Related

Directly give a new Control an EventHandler

I'm looping a collection of strings, coming from a database; for each entry, I create a new Button which is then added to a FlowLayoutPanel.
The Text of each Button is set to the current item in the string collection.
I'd like to assign an EventHandler to the Click event of each Button, however I am only able to access the Properties of a Button.
I have to cast the last entry of the FlowLayoutPanel's Controls collection to Button and add the Event Handler to this instance.
Does anyone know the reason why I can't access anything else then Properties? Is there a cleaner way of coding that?
List<string> temp = Database.GetNames();
foreach(string s in temp)
{
flp_main.Controls.Add(new Button()
{
Text = s.name
});
Button b = (Button)flp_main.Controls[flp_main.Controls.Count - 1];
b.Click += B_Click;
}
Asking for Improvements on Code Quality

Is there any way that I could "array" a group of pictureBox to use in a for statement? [duplicate]

Has C# indexed control arrays or not? I would like to put a "button array" for example with 5 buttons which use just one event handler which handles the index of all this 5 controls (like VB6 does). Else I have to write for each of these 5 buttons one extra event handler. And if I have 100 buttons, I need 100 event handlers? I mean something like that:
TextBox1[i].Text="Example";
It could make coding definitely easier for me to work with control arrays. Now I have seen, that C# at least has no visible array functionality on user controls and no "index" property on the user controls. So I guess C# has no control arrays, or I must each element call by known name.
Instead of giving 100 TextBoxes in a for loop 100 incrementing values, I have to write:
TextBox1.Text = Value1;
TextBox2.Text = Value2;
...
...
TextBox100.Text = Value100;
A lot of more work + all these 100 event handlers each for one additional TextBox extra.
I know I'm a little late to this party, but this solution will work:
Make a global array:
TextBox[] myTextBox;
Then in your object's constructor, after the call to
InitializeComponent();
initialize your array:
myTextBox = new TextBox[] {TextBox1, TextBox2, ... };
Now you can iterate your array of controls:
for(int i = 0; i < myTextBox.Length; i++)
myTextBox[i].Text = "OMG IT WORKS!!!";
I hope this helps!
Pete
As I mentioned in comment to a solution by HatSoft, C# Winforms does not allow you to create control arrays like old VB6 allowed us. The nearest I think we can get to is what HatSoft and Bert Evans in their posts have shown.
One thing that I hope would satisfy your requirement is the event handler, you get a common event handler and in the event handler when you typecast the "sender" you get the control directly just like you would in VB6
C#
TextBox textBox = sender as TextBox;
VB6
TextBox textBox = TextBox1[i];
So the only trouble you might have is wiring those 100 TextBoxes to a single event handler, if you are not creating the controls dynamically through code rather creating it manually at design time then all one can suggest is group them in a container like say Panel. Then on Form Load wire them all up to a single event handler like this:
foreach (Control control in myTextBoxPanel.Controls)
{
if(control is TextBox)
control.TextChanged += new EventHandler(control_TextChanged);
}
Just create one handler and point all the buttons to it.
var ButtonHandler = (sender, args) => {
var clicked = (Button)sender;
if (clicked.Text == "whatever")
//do stuff
else
//do other stuff
};
button1.Click += ButtonHandler;
button2.Click += ButtonHandler;
Alternatively, if you are creating controls in code, you could use one of the techniques specified in this answer.
Instead of giving 100 TextBoxes in a for loop 100 incrementing values, I have to write:
for(int i = 0; i <100; i++)
{
TextBox t = new TextBox(){ Id = "txt_" + i, Value = "txt_" + i};
t.TextChanged += new System.EventHandler(this.textBox_Textchanged);
Page.Controls.Add(t);
}
//and for event on TextChanged
private void textBox_Textchanged(object sender, EventArgs e)
{
TextBox textBox = sender as TextBox;
if (textBox != null)
{
////
}
}
Another thing to note: if you really need to edit 100 strings on one form, you should probably think about whether 100 text boxes is really the best way to do it. Perhaps a ListView, DataGridView, or PropertyGrid would be better suited.
This applies almost any time you think you need a huge array of controls.
If you are working with Web Forms and not MVC, you can acces a collection of controls on the page as shown in Using the Controls Collection in an ASP.NET Web Page. Essentially the controls collection is a tree with the page hosting the first level of child controls and some items having children of their own. See How to: Locate the Web Forms Controls on a Page by Walking the Controls Collection for an example of how to follow the tree.
Also, see How to: Add Controls to an ASP.NET Web Page Programmatically.
You can use the same event handler for multiple items as long as the signature required is the same.
For Windows Forms this is nearly identical since they're based on similar architectural models, but you'll want Control.Controls Property and How to: Add Controls to Windows Forms.
Keeping it simple:
TextBox[] keybox = new TextBox[16]; //create an array
for (int i=0; i<16; i++)
{
keybox[i] = new TextBox(); //initialize (create storage for elements)
keybox[i].Tag = i; //Tag prop = index (not available at design time)
keybox[i].KeyDown += keybox_down; //define event handler for array
}
private void keybox_down(object sender, KeyEventArgs e)
{
int index = (int)((TextBox)sender).Tag //get index of element that fired event
...
}

How to dynamically create EventHandlers for dynamically created buttons? C# VS2010

so, I have a form that is dynamically populated with textboxes and buttons.
How can I create EventHandlers for each of those buttons dynamically (ex: it generates 20 buttons, I need 20 eventhandlers). Each button will have the same function (to delete something from a database) but I need the program to know whenever any one of them is clicked to trigger that code.
// also, the button creation code is within a while() so I can't use it ouside that while (just pointing that out)
Code:
public void LoadElements()
{
//more code here
while(some condition)
{
// more code above
Button b = new Button();
b.Text = "Delete";
b.Name = "button" + j;
b.Location = new Point(240, Y);
Controls.Add(b);
// more code bellow
}
// more code here
}
Assign them like you would for any other event in your code. You can simply add an event handler doing something like:
b.Click += b_Click
Add in the loop:
b.Click+=New Eventhandler(b_Click);
(Just press TAB twice after typing b.Click+=).
Define the function b_Click outside of the loop. It will be invoked when anyone of those button is clicked.

Adding buttons programmatically to a TabControl (TabPage)

I read this topic (Adding buttons to a TabControl Tab in C#) but I don't figure out why my code below add one button only to the tabpage.
I've obviously debugged that the foreach works properly.
foreach (string line in File.ReadAllLines(#"C:\quicklauncher.ini"))
{
TabPage page = new TabPage(foldername);
DirectoryInfo d = new DirectoryInfo(line);
foreach (FileInfo file in d.GetFiles("*.*"))
{
Button button = new Button();
button.Text = file.Name;
button.Click += new EventHandler(button_Click);
page.Controls.Add(button);
}
tabControl.TabPages.Add(page); //add our tab page to the tab control
}
Thanks,
Steve
You thought it added only 1 button for you but in fact it did not, it added all the buttons for you but those buttons had the same Location (which is (0,0) by default). That's why you did think there was only 1 button (because you saw only 1 last button on top of others).
You added buttons automatically to your tabpage, so you should have some rule to locate them, I'm not sure what that rule is but I suppose you want to line them up vertically (just an example), I'm going to correct your code to achieve such a thing, at least you will see it work, and in fact all the buttons are added normally:
//you need some variable to save the next Top for each new button:
//let's call it nextTop:
int nextTop = 0;
foreach (FileInfo file in d.GetFiles("*.*"))
{
Button button = new Button { Top = nextTop,
Text = file.Name };
button.Click += new EventHandler(button_Click);
page.Controls.Add(button);
nextTop += button.Height + 5; //it's up to you on the
//Height and vertical spacing
}
//...
You can also try using some layout control like FlowLayoutPanel and TableLayoutPanel to contain all the buttons, they can help arrange your buttons in some way you may want, just try it.

how to Creating buttons in a running application (runtime) plus its onclick event function using C#?

I want to create buttons or list of items on the basis of number of items in my database or from list of items in my array and for each item create a onclick function for either buttons or any list of items
How about:
int y = 10;
foreach (string name in names)
{
Button button = new Button();
button.Text = name;
button.Position = new Point(10, y);
y += 20;
button.Click += HandleButtonClick;
Controls.Add(button);
}
You might also store the buttons in an array or a list... there's nothing particularly special about GUI controls that stops you from creating them at execution time just like any other object.
If that doesn't help, please give more information about what you need to do that the above doesn't help you with.
I have done it also by looking at Visual Studio code.

Categories

Resources