C# Add Controls To Panel In a Loop - c#

I wish to add a button for every line in a file to a panel.
My code so far is:
StreamReader menu = new StreamReader("menu.prefs");
int repetition = 0;
while(!menu.EndOfStream)
{
Button dynamicbutton = new Button();
dynamicbutton.Click += new System.EventHandler(menuItem_Click);
dynamicbutton.Text = menu.ReadLine();
dynamicbutton.Visible = true;
dynamicbutton.Location = new Point(4+repetition*307, 4);
dynamicbutton.Height = 44;
dynamicbutton.Width = 203;
dynamicbutton.BackColor = Color.FromArgb(40,40,40);
dynamicbutton.ForeColor = Color.White;
dynamicbutton.Font = new Font("Lucida Console", 16);
dynamicbutton.Show();
menuPanel.Controls.Add(dynamicbutton);
repetition++;
MessageBox.Show(dynamicbutton.Location.ToString());
}
menu.Close();
The problem is that only the first control gets created.

The code looks fine but there could be a following situations.
1.You might have only one entry in the file, so you are experiencing only One Button added to the panel.
2.Your panel width is smaller than the sum of all the dynamic buttons width.
I suspect no 2 is the main reason that is causing problem.
So, I recommend that you use FlowLayoutPanel. To add a dynamic content as it automatically layout all the child controls.

Each time it is generating the same name for dynamic controls. That's the reason why it is showing only the last one. It simply overwrites the previous control each time.

int x = 4;
int y = 4;
foreach(PhysicianData pd in listPhysicians)
{
x = 4;
y = panPhysicians.Controls.Count * 30;
RadioButton rb = new RadioButton();
rb.CheckedChanged += new System.EventHandler(rbPhysician_CheckedChanged);
rb.Text = pd.name;
rb.Visible = true;
rb.Location = new Point(x, y);
rb.Height = 40;
rb.Width = 200;
rb.BackColor = SystemColors.Control;
rb.ForeColor = Color.Black;
rb.Font = new Font("Microsoft Sans Serif", 10);
rb.Show();
rb.Name = "rb" + panPhysicians.Controls.Count;
panPhysicians.Controls.Add(rb);
}

Try this code
StreamReader menu = new StreamReader("menu.prefs");
var str = menu.ReadToEnd();
var items = str.Split(new string[] {"\r\n" } , StringSplitOptions.RemoveEmptyEntries);
foreach (var item in items)
{
Button dynamicbutton = new Button();
dynamicbutton.Click += new System.EventHandler(menuItem_Click);
dynamicbutton.Text = item;
dynamicbutton.Visible = true;
dynamicbutton.Location = new Point(4+repetition*307, 4);
dynamicbutton.Height = 44;
dynamicbutton.Width = 203;
dynamicbutton.BackColor = Color.FromArgb(40,40,40);
dynamicbutton.ForeColor = Color.White;
dynamicbutton.Font = new Font("Lucida Console", 16);
dynamicbutton.Show();
menuPanel.Controls.Add(dynamicbutton);
repetition++;
}

The problem with Panel and similar controls other than the FlowLayoutPanel is when you create a control and a second one, the second is created at the same position if you are not changing it's location dynamically or setting it according to the other already added controls. Your control is there, it's in the back of the first control.
A flowLayoutPanel is better as it will add the controls next to each other as you add them while compromising more finer control at their positioning.

I also have similar problems with panels. For what you are doing it could be useful to just add strings to a listbox rather than using labels and a panel. That should be simpler.

Related

How to add radio buttons dynamically in Windows form?

I need to add radio buttons dynamically in my windows form and in horizontal mode.
for (int i = 0; i <= r.Count; i++)
{
RadioButton rdo = new RadioButton();
rdo.Name = "id";
rdo.Text = "Name";
rdo.ForeColor = Color.Red;
rdo.Location = new Point(5, 30 );
this.Controls.Add(rdo);
}
You could do something like this:
FlowLayoutPanel pnl = new FlowLayoutPanel();
pnl.Dock = DockStyle.Fill;
for (int i = 0; i < 4; i++)
{
pnl.Controls.Add(new RadioButton() { Text = "RadioButton" + i });
}
this.Controls.Add(pnl);
You could also add the FlowLayoutPanel in the designer and leave that part out in the code.
To get the selected RadioButton use a construct like this:
RadioButton rbSelected = pnl.Controls
.OfType<RadioButton>()
.FirstOrDefault(r => r.Checked);
To use this the FlowLayoutPanel needs to be known in the calling method. So either add it to the Form in the designer (Thats what I would prefer) or create it as an instance member of the form and add it at runtime (this has no benefit).
You can do something like this
//This is my dynamic data list
List<ItemType> itemTypeData = new List<ItemType>()
RadioButton[] itemTypes = new RadioButton[ItemType.Count];
int locationX = 0;
for (int i = 0; i < ItemType.Count; i++)
{
var type = ItemType[i];
itemTypes[i] = new RadioButton
{
Name = type.Code,
Text = type.Code,
AutoSize = true,
Font = new System.Drawing.Font("Calibri", 11F, FontStyle.Regular),
Location = new Point(156 + locationX, 88),
};
this.Controls.Add(itemTypes[i]);
locationX += 80;
}
This works fine for me

C# How to put RadioButton inside Panel

I have searched everywhere, but the procedure are so painful. How to put multiple RadioButton into a panel programatically without using toolbox. I'm using WinForms. After several suggestion/s, I still can't add the radiobuttons inside the panel.
public partial class Form1 : Form
{
RadioButton[] RadioButton_WallFirstStorey_Yes = new RadioButton[100];
RadioButton[] RadioButton_WallFirstStorey_No = new RadioButton[100];
Panel[] Panel_WallFirstStorey = new Panel[100];
int CheckBoxWidth = 100;
public Form1()
{
InitializeComponent();
//code
//procedure
}
private void InitializeRadioButton_Wall(RadioButton RadioButtonX)
{
RadioButtonX.AutoSize = true;
RadioButtonX.Font = SystemFonts.DefaultFont;
RadioButtonX.BackColor = Color.Transparent;
Controls.Add(RadioButtonX);
}
private void InitializePanel_Wall(Panel PanelX)
{
PanelX.BackColor = Color.PaleTurquoise;
PanelX.BorderStyle = BorderStyle.Fixed3D;
PanelX.BringToFront();
Controls.Add(PanelX);
}
private void MyProcedure()
{
int i;
for (i = 1; i <= 100; i++)
{
Panel_WallFirstStorey[i] = new Panel();
InitializePanel_Wall(Panel_WallFirstStorey[i]);
Panel_WallFirstStorey[i].Location = new Point(Label_SeparatorLineVertical[ColumnMinimum + i].Location.X, Label_SeparatorLineHorizontal[RowMinimum + i].Location.Y);
Panel_WallFirstStorey[i].Width = (Label_SeparatorLineVertical[ColumnMaximum].Location.X - Label_SeparatorLineVertical[ColumnMinimum].Location.X) / (ColumnMaximum - ColumnMinimum);
Panel_WallFirstStorey[i].Height = CheckBoxWidth;
Panel_WallFirstStorey[i].SendToBack();
}
for (i = 1; i <= 100; i++)
{
RadioButton_WallFirstStorey_Yes[i] = new RadioButton();
RadioButton_WallFirstStorey_No[i] = new RadioButton();
Panel_WallFirstStorey[i].Controls.Add(RadioButton_WallFirstStorey_Yes[i]);//I add this stuff
Panel_WallFirstStorey[i].Controls.Add(RadioButton_WallFirstStorey_No[i]);//I add this stuff
InitializeRadioButton_Wall(RadioButton_WallFirstStorey_Yes[i]);
InitializeRadioButton_Wall(RadioButton_WallFirstStorey_No[i]);
RadioButton_WallFirstStorey_Yes[i].Text = "Yes";
RadioButton_WallFirstStorey_No[i].Text = "No";
RadioButton_WallFirstStorey_Yes[i].Location = new Point(Panel_WallFirstStorey[i].Width / 3, 0);
RadioButton_WallFirstStorey_No[i].Location = new Point(Panel_WallFirstStorey[i].Width * 2 / 3, 0);
RadioButton_WallFirstStorey_Yes[i].Font = SystemFonts.DefaultFont;
RadioButton_WallFirstStorey_No[i].Font = SystemFonts.DefaultFont;
RadioButton_WallFirstStorey_Yes[i].BringToFront();
RadioButton_WallFirstStorey_No[i].BringToFront();
}
}
}
Wow, your code is wrong in so many ways.... It creates controls over and over whenever a panel is painted, but it never really adds them anywere.
To add a radio button b to a panel p, it would be enough to do this:
RadioButton b = new RadioButton();
// Set properties for button here (text, location, handlers, etc.)
p.Controls.Add(b);
I'd try the following procedure instead of yours:
private void MyProcedure()
{
for (i = 1; i <= 100; i++)
{
RadioButton_WallFirstStorey_Yes[i] = new RadioButton();
RadioButton_WallFirstStorey_No[i] = new RadioButton();
InitializeRadioButton_Wall(RadioButton_WallFirstStorey_Yes[i]);
InitializeRadioButton_Wall(RadioButton_WallFirstStorey_No[i]);
RadioButton_WallFirstStorey_Yes[i].Text = "Yes";
RadioButton_WallFirstStorey_No[i].Text = "No";
RadioButton_WallFirstStorey_Yes[i].Location = new Point(Panel_WallFirstStorey[i].Location.X + Panel_WallFirstStorey[i].Width / 3, Panel_WallFirstStorey[i].Location.Y);
RadioButton_WallFirstStorey_No[i].Location = new Point(Panel_WallFirstStorey[i].Location.X + Panel_WallFirstStorey[i].Width * 2 / 3, Panel_WallFirstStorey[i].Location.Y);
Panel_WallFirstStorey[i].Controls.Add(RadioButton_WallFirstStorey_Yes[i]);
Panel_WallFirstStorey[i].Controls.Add(RadioButton_WallFirstStorey_No[i]);
}
}
The following code indicates you're still doing it wrong, adding the radio buttons to the form itself, but positioning them as if you had added them to the panel:
RadioButton_WallFirstStorey_Yes[i].Location = new Point(Panel_WallFirstStorey[i].Location.X + Panel_WallFirstStorey[i].Width / 3, Panel_WallFirstStorey[i].Location.Y);
If you added the button to the panel, it would most probably be invisible because it is outside the panel. If you added the button to the panel, you'd have to use coordinates relative to the panel's client area.
RadioButton_WallFirstStorey_Yes[i].Location = new Point(Panel_WallFirstStorey[i].Width / 3, 0);
RadioButton_WallFirstStorey_No[i].Location = new Point(Panel_WallFirstStorey[i].Width * 2 / 3, 0);
Your update code shows clearly where your error is:
private void InitializeRadioButton_Wall(RadioButton RadioButtonX)
{
RadioButtonX.AutoSize = true;
RadioButtonX.Font = SystemFonts.DefaultFont;
RadioButtonX.BackColor = Color.Transparent;
// REMOVE THIS LINE!!
Controls.Add(RadioButtonX);
}
The last line adds the radio button to the form. As we've been telling you all the time. Remove the line I marked above. Then, the radio buttons will be added to the panels only. After that it is a question of getting the positions right.
You can for example create a panel (or a GroupBox) and in a loop add the RadioButtons.
It should work like with any other control in Winforms.
// Adds 10 Radiobuttons with the name "Radio <number>"
public Form1()
{
InitializeComponent();
for (int n = 0; n < 10; n++)
{
// First instantiate a new RadioButton.
RadioButton button = new RadioButton();
// Now the name of the button.
button.Text = "Radio" + n;
// Dock the button to the top of the GroupBox (to put them in order)
button.Dock = DockStyle.Top;
// Add the button to the GroupBox.
this.groupBoxRadio.Controls.Add(button);
}
}
Your question is not very clear, and no code for context, but you should be able to create an instance of a new radiobutton and add it to the controls of the panel.
It may also be best to use RadioButtonList like Harvey has mentioned, but to try to answer your question:
var someRadioBtn = new RadioButton();
// set properties...
pnlMyPanel.Controls.Add(someRadioBtn);

Adding dynamic controls to winform not working

I am creating dynamic PictureBox and label in WinForms. For this I have created a method which creates these items on the basis of given integer. In the first run while loading the form, its works smoothly, but when I pass any integer from a dropdown box, it does not make any changes. I tried debugging the code, and all the labels are created accordingly but it is not reflected in the winForm. I tried using Invalidate, Update, Refresh but non of them worked.
Here is the method that I have implemented.
private void createPictureBox(int size)
{
//this.Controls.Clear();
panel1.Controls.Clear();
Label[] ParameterLabel = new Label[size];
PictureBox[] ParameterBack = new PictureBox[size];
int y_value = 11;
this.Refresh();
for (int i = 0; i < size; ++i)
{
ParameterLabel[i] = new Label();
ParameterLabel[i].Text = "Test Text";
ParameterLabel[i].Font = new System.Drawing.Font("Calibri", 8, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(128)));
ParameterLabel[i].ForeColor = System.Drawing.Color.White;
ParameterLabel[i].BackColor = System.Drawing.Color.FromArgb(1, 0, 64);
ParameterLabel[i].Size = new System.Drawing.Size(145, 20);
ParameterLabel[i].Location = new Point(30, y_value);
ParameterLabel[i].Anchor = AnchorStyles.Left;
ParameterLabel[i].Visible = true;
ParameterBack[i] = new PictureBox();
ParameterBack[i].Image = Image.FromFile(STR_SETTING_PATH + "\\" + STR_IDEA_NO_XXXXX + "_01_nv.png");
ParameterBack[i].Size = new System.Drawing.Size(400, 32);
ParameterBack[i].Location = new Point(2, y_value - 10);
ParameterBack[i].Anchor = AnchorStyles.Left;
ParameterBack[i].Visible = true;
//this.Controls.Add(ParameterBack[i]);
y_value += 37;
}
panel1.Controls.AddRange(ParameterLabel);
panel1.Controls.AddRange(ParameterBack);
panel1.Invalidate();
}
Who can you distinguish between controls created in the first call and those created in other calls? I've tested your function with a tiny change, it seems to be working fine:
int CallIndex = 0; // this is on the form level
private void button1_Click(object sender, EventArgs e)
{
createPictureBox(3);
CallIndex += 1;
}
private void createPictureBox(int size)
{
// this has the exact same code as your method (copy-paste into my visual studio),
// except this change:
// ParameterLabel[i].Text = "Test Text";
ParameterLabel[i].Text = string.Format("Test {0}", CallIndex); // instead of the row above
}
I did remove the previously added controls and added the new one after which apparently solved my problem. The problem was due to piling of Controls one over another. I first removed the previously created controls using
this.Controls.Remove(UserControl1);
Then re-created its instance, which solved my problem.

How to set different events for dynamically created element

Im trying to create event with different index for dynamically created GroupBox. With my actual code event for every groupbox is that same. How can i make event with different index for every groupbox? My Code:
public void LoadGry()
{
// GroupBox groupbox = new GroupBox();
Label nazwagry = new Label();
for(int i = 0; i < myCollection.Count; i++)
{
GroupBox groupbox = new GroupBox();
groupbox.Text = myCollection[i];
groupbox.Size = new Size(290, 131);
groupbox.Location = new Point(6, 150 * (myCollection.Count - i - 1));
groupbox.ForeColor = Color.White;
Label label1 = new Label();
label1.Text = groupbox.Text;
label1.AutoSize = true;
label1.Location = new Point(groupbox.Location.X + 80, groupbox.Location.Y + 20);
groupbox.Controls.Add(label1);
Gry.Controls.Add(label1);
PictureBox picturebox = new PictureBox();
picturebox.Location = new Point(groupbox.Location.X + 5, groupbox.Location.Y + 20);
picturebox.Size = new Size(75, 75);
picturebox.SizeMode = PictureBoxSizeMode.StretchImage;
picturebox.LoadAsync(myCollection3[i]);
groupbox.Click += new EventHandler(delegate {groupboxclick(groupbox, picturebox, i);});
Label label2 = new Label();
label2.Text = "Status: " + "Aktualny";
label2.ForeColor = Color.Green;
label2.AutoSize = true;
label2.Location = new Point(label1.Location.X, label1.Location.Y + 20);
Gry.Controls.Add(label2);
Label zapiszopis = new Label();
zapiszopis.Text = myCollection4[i];
zapiszopis.Visible = false;
Gry.Controls.Add((Control)groupbox);
//MessageBox.Show("pokaz mi wysokosc");
}
}
private void groupboxclick(GroupBox groupbox, PictureBox picturebox, int itest)
{
groupbox.ForeColor = Color.Aqua;
this.pictureBox1.BackgroundImage = picturebox.BackgroundImage;
opishacka.Text = myCollection4[itest];
}
The problem is that the event setup is using the variable K value. For use the number instead you probably needs to create an expression manually to use the current value in each case.
BUT
You can easily do what you want using the following properties to attach values to controls.
1-) Tag in WinForms & WPF:
// Setup
pictureBox.Tag = i;
// Event
int i = (int) pictureBox.Tag;
2-) ViewState in WebForms
// Setup
ViewState[pictureBox.UniqueID] = i;
// Event
int i = (int) ViewState[pictureBox.UniqueID];
You can use many other techniques. I only post one for each popular framework. I guest that you are in a WinFors project.
Hope this help!

Dynamic creation of control

for (int i = 0; i < 200; i++)
{
Control control = new Control();
control = new CheckBox();
Size size = control.Size;
Point point = new Point(20, 22);
control.Location = point;
int width = size.Width + 5;
i += width;
list.Add(control);
}
foreach(Control c in list)
{
}
how do I create a new instance of checkbox? Because this way I am getting just one checkbox each time. I want to get three checkbox in each row.
Is this winforms? A first point: you don't need the new Control() each time (you simly discard it anyway when you new CheckBox(). How exactly do you want the layout to appear? Can you describe it a bit more please?
I imagine TableLayoutPanel might be a reasonable start...
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Form form = new Form();
TableLayoutPanel layout = new TableLayoutPanel();
layout.Dock = DockStyle.Fill;
form.Controls.Add(layout);
layout.AutoScroll = true;
layout.ColumnCount = 3;
// size the columns (choice just to show options, not to be pretty)
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 200));
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50));
layout.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
layout.GrowStyle = TableLayoutPanelGrowStyle.AddRows;
for (int i = 0; i < 200; i++)
{
CheckBox chk = new CheckBox();
chk.Text = "item " + i;
layout.Controls.Add(chk);
}
Application.Run(form);
}
Otherwise, you'll need to manually set the Location (or Top and Left) of each; not simple.
Your code has problems. Let's work from sample code rather than a lesson. I'll create a Panel first, nice if you want to remove the checkboxes you created. You'd probably be interested in the user clicking a checkbox so lets add an event for that. Start a new WF project and drop a button on the form. Double click it, then paste this code:
private void button1_Click(object sender, EventArgs e) {
// Give the 3 checkboxes a decent spacing
int height = this.Font.Height * 3 / 2;
// Create the panel first, add it to the form
Panel pnl = new Panel();
pnl.Size = new Size(100, 3 * height);
pnl.Location = new Point(10, 5);
this.Controls.Add(pnl);
// Make three checkboxes now
for (int ix = 0; ix < 3; ++ix) {
CheckBox box = new CheckBox();
box.Size = new Size(100, height);
// As pointed out, avoid overlapping them
box.Location = new Point(0, ix * height);
box.Text = "Option #" + (ix + 1).ToString();
box.Tag = ix;
// We want to know when the user checked it
box.CheckedChanged += new EventHandler(box_CheckedChanged);
// The panel is the container
pnl.Controls.Add(box);
}
}
void box_CheckedChanged(object sender, EventArgs e) {
// "sender" tells you which checkbox was checked
CheckBox box = sender as CheckBox;
// I used the Tag property to store contextual info, just the index here
int index = (int)box.Tag;
// Do something more interesting here...
if (box.Checked) {
MessageBox.Show(string.Format("You checked option #{0}", index + 1));
}
}
It looks like you get your 200 instances, all placed at the same point.
Instantiate 3 new checkboxes inside your loop body, set their properties accordingly and add each of them to the list. After the code above is complete, you will have 600 checkboxes.
list.Add(Control1);
list.Add(Control2);
list.Add(Control3);
I am not sure about what you are trying to do, but I cleaned up your code a bit:
for (int i = 0; i < 200; i++)
{
Control control = new CheckBox();
control.Location = new Point(20, 22);
i += control.Size.Width + 5;
list.Add(control);
}
You should not add a new instance to the list if you want to add the control you just made.
Also:
Control control = new Control();
control = new CheckBox();
Is a bit redundant. Also to not get one control at the same spot multiple times you should alter the point. Hope this helps

Categories