How do I orderly generate controls underneath eachother? - c#

I have a class which generates a form and controls. The controls vary between buttons, radio controls, check boxes and labels. The idea is to neatly create the form with a label above each control. The problem is that I cannot seem to find the formula or way to neatly organise/space them. It works fine when I have just text boxes, but I'm not sure how to handle larger controls, like check box lists. Here's an example of how I handle text boxes:
case "Text":
TextBox tbx = new TextBox();
tbx.Name = df.Value.Name;
tbx.Text = (df.Value.DefValue != null) ? df.Value.DefValue : "";
tbx.Location = new Point(lbl.Location.X, lbl.Location.Y + 20);
f.Controls.Add(tbx);
break;
Mind that this is all in a foreach loop. This is the part that precedes it (label):
if (i == 0)
{
lbl.Location = new Point(10, 10);
}
else
{
lbl.Location = new Point(10, (i * 50) + 10);
}
This neatly sorts the text boxes and labels out with an even spacing. Can anyone offer me some advice on how to handle different controls? I want to place them underneath eachother but keep at least 10 pixels spacing from the bottom of each control to the top of the next label.
Thank you in advance.

Use a tablelayout. You can take a look at how the designer does it in the code behind file.
For the spacing, fill in the "margin" property of your controls. 5 on top and 5 at the bottom should do it.

Related

Resizing and Collapsing label in winforms

first time poster, sorry if something isn't as it should be.
I'm new to Winforms and am trying to build a simple application that will display multiple features of an item (like Size, Composition, etc.). Each Characteristic has a Name, can have a Descritpion, and some can have sub-characteristics (having also a name and sometimes a descritpion).
I want to display them one under the other, with the Name of the feature on a blue background that span the whole width of the container, with the description underneath. The name will be (or have) a button (or similar) that when clicked collapse or expand the description. This must be created at run time because I don't know how many feature an object has until the user generate it.
The issues I'm running in are that either I can't span the blue background the whole width of the container (if using a FlowLayoutPanel), or I have some issue with the Description text being not the right size (either it wraps but is too big, or it doesn't wrap and then I can't see the whole text).
Some things are fixed, mainly the number of main sections (like Size, Composition, Weather, etc.), so I can prepare the skeleton before runtime.
The closest i've been to making it work gives this. This issue here is that the height of the Panel which the description label is embded in is fixed, and if I put in in Autosize, the text don't show (probably because the label is in Fill dock style). Just as information, this is what it looks like when collapsed (this is indeed what I'm looking for)
I know some library exists with collapsible panels, but I'd rather try to make it work without external libraries. Thanks in advance for any help !
This is the code that produces the results in the screenshots :
Panel SizeDescrPanel = new Panel();
SizeDescrPanel.Dock = DockStyle.Top;
//SizeDescrPanel.AutoSize = true;
SizeDescrPanel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
SizeDescrPanel.BackColor = Color.Bisque;
SizePanel.Controls.Add(SizeDescrPanel);
Label SizeDescrLbl = new Label();
SizeDescrLbl.Text = Lorem;
SizeDescrLbl.AutoSize = false;
SizeDescrLbl.Dock = DockStyle.Fill;
SizeDescrLbl.BackColor = Color.BurlyWood;
SizeDescrPanel.Controls.Add(SizeDescrLbl);
/*using(Graphics g = CreateGraphics())
{
SizeF size = g.MeasureString(SizeDescrLbl.Text, SizeDescrLbl.Font, SizePanel.Width);
SizeDescrPanel.Height = (int) Math.Ceiling(size.Height);
}*/
Panel SizeNamePanel = new Panel();
SizeNamePanel.Dock = DockStyle.Top;
SizeNamePanel.BackColor = Color.Cyan;
SizeNamePanel.AutoSize = true;
SizePanel.Controls.Add(SizeNamePanel);
Button SizeNameBtn = new Button();
SizeNameBtn.Text = "<Size Name> ..." + SizeDescrLbl.Height;
SizeNameBtn.TextAlign = ContentAlignment.MiddleLeft;
SizeNameBtn.FlatStyle = FlatStyle.Flat;
SizeNameBtn.AutoSize = true;
SizeNamePanel.Controls.Add(SizeNameBtn);
SizeNameBtn.Click += delegate { HideShowPanel(SizeDescrPanel); };
It,s a test project, so later I'll put that in different methods. What isn't shown here :
I have a main panel set to Fill containing everything.
The text "SIZE" is a label set to Top
Under it is another Panel (SizePanel) that is set to Top and Autosize is at True. This is the Panel inside which I'm puttin my size name and my size description. If I had a subfeature, it would be included (ideally) inside descritpion with the same configuration (button expanding/collapsing the descritpion of the SubFeature)

Drawing a label array in c#

For my project I would need to create clickable tiles sort of like a grid. To do so I have decided to try using an array of labels and clicking on any one of them would cause a mouse click event corresponding to the label clicked. I don't want to use the Visual Studio drag and drop labels to draw the 220 I need so i decided to create an array of Labels. Here is the code I am using to test out the use of the array of labels:
Label[] Tiles = new Label[10];
for (int i = 0; i != 10; i++)
{
for (int n = 0; n != 22; n++)
{
Tiles[i] = new Label();
Tiles[i].Size = new Size(62, 62);
Tiles[i].Location = new System.Drawing.Point(n * 62 + 118, 106 + i * 62);
Tiles[i].Text = (i+n).ToString();
Tiles[i].Name = (i + n).ToString();
Tiles[i].AutoSize = true;
Tiles[i].Click += new System.EventHandler(this.label1_Click);
}
}
I am using this code In the Form1_Load method but the problem is that it doesn't throw an error but also does not actually get the labels on the Form, it just initializes the labels but does not draw them, does someone know how to actually add them to the Form.
This is really easy to do!
In your innermost for loop, add this line:
this.Controls.Add(Tiles[i]);
It first gets all the controls on the form, then add the label in it!
However, I would advise you to add the labels to a Panel, just because since you're creating a grid, you should probably group the labels together using a Panel.
Create a panel in the designer, call it labelPanel or whatever, and call this method instead in the innermost for loop:
this.labelPanel.Controls.Add(Tiles[i]);
Please note that since the position of the labels are now relative to the panel, you need to adjust them again.
You have to add that labels to the form. like, put one groupbox in your form and named it as group1.
now add Labels to that group.
group1.Controls.Add(Tiles[i]);

How to rearrange a WinForms Controls during runtime?

In my project I wanted to order controls at run-time, like in DataGridView how we'll use display-index to order fields in the grid.
In design level I added 3 TextBoxs and 1 ComboBox next to each other & in run time i wanted to order them, for example, first 2 TextBoxs should show, then the ComboBox and then the other TextBox.
Is it possible to rearrange the controls in run-time?
Every Control in Windows Forms has a Location property. You can easily change the location of the control by changing this property:
textBox1.Location = new Point(10, 50); // Puts the TextBox at coordinates (10,50)
The coordinates are relative to upper-left corner of the control container (the form itself for example).
In your case, you can easily arrange the controls like this:
Control[] controls = new Control[] { textBox1, textBox2, comboBox3, textBox3 }; // These are your controls
int left = 20, top = 50; // or any other value
foreach (c in controls)
{
c.Location = new Point(left, top);
left += c.Width + 10; // space 10 pixels between controls
}

C# Window Form Application, how to efficiently create a dynamic panel on a window form

I would like to create a few panel dynamically in my window form application. Each panel will consist of 3 labels and one text box and one button. Now I know I can hard code this all at once by declaring each variable every time, but it takes a lot of coding and it is obviously not efficient at all.
So my question is: Is there a way to create pre-define panel dynamically where each time a panel is created will have a predefined layout setup already. So all i need to do is to add a panel, its location and size every time, and all the content(like labels, text-box and button) inside the panel are already setup with their location associated with the panel itself. Do I really have to create a class just for that?
Thanks in advance for read and taking your time.
Create Windows Forms control or user control, see http://msdn.microsoft.com/en-us/library/6hws6h2t.aspx
Create a user control, and place on it whatever you like (your labels). Expose public methods/properties of that control so you can control the contents of it. Place as many of those on the form as you like, they will all look and behave same.
Here is an example you can play with...
for (int i = 1; i < 5; i++)
{
var panel1 = new Panel() { Size = new Size(90, 80), Location = new Point(10, i * 100), BorderStyle = BorderStyle.FixedSingle };
panel1.Controls.Add(new Label() { Text = i.ToString(), Location = new Point(10, 20) });
panel1.Controls.Add(new Label() { Text = i.ToString(), Location = new Point(10, 40) });
panel1.Controls.Add(new Label() { Text = i.ToString(), Location = new Point(10, 60) });
Controls.Add(panel1);
}

Creating a dynamic UI in winforms

If I want to create a winform with dynamic UI controls appearing, what's the best way to do that?
I have a form with a textbox, a button1 to the right of it, a listbox underneath, and a button2 underneath the listbox. Pressing button1 should generate another textbox underneath the first textbox and the listbox/button2 should be shifted down. If anyone's used Adobe Bridge before, the batch rename window is an example of what I'm talking about.
I was thinking of simply adding textboxN.Height to this.Size, then textboxN.Height to each of the controls (except the first textbox) Y position so they all get shifted down by textboxN.Height pixels. But I think there's a better way of doing this. Rather, is Winforms suitable for something like this?
You -could- just add the height of the TextBox to the form's size, but tbh it would be better to use a constant that dictates the size of the TextBoxes, and then add that.
For moving the listBox/button2, anchor them to the bottom of the form, and they'll automatically stay at the same distance from the bottom of the form.
As for dynamic generation, use a List (or a Stack, depending on what exactly you're doing with it).
partial class Form1 : Form
{
List<TextBox> textBoxes = new List<TextBox>(); // or stack
const int textBoxWidth = 200; // control variables for TextBox placement
const int textBoxHeight = 50;
const int textBoxMargin = 5;
void button1_Click(object sender, EventArgs e)
{
this.Height += textBoxHeight + textBoxMargin;
TextBox tb = new TextBox();
if (textBoxes.Count == 0)
{
tb.Top = textBoxMargin;
}
else
{
tb.Top = ((textBoxHeight + textBoxMargin) * textBoxes.Count) + textBoxMargin;
}
tb.Left = textBoxMargin;
tb.Height = textBoxHeight;
tb.Width = textBoxWidth;
textBoxes.Add(tb);
this.Controls.Add(tb);
}
}
That should work. The thing with the method here is pretty much all of the placement customisation can be done with the constant values.
Is it best to do it in WinForms? Well, there's certainly no real reason to not do it in WinForms, this functionality is easy enough to implement. I'm a WPF guy myself but this is still legit.
Edited for logic errors

Categories