I have a problem with a FlowLayoutPanel and I don't know how to solve it.
I'm placing two FlowLayoutPanels inside another; the second inner flp has 3 buttons inside.
The properties from FlowLayoutPanel child are:
FlowDirection = LeftToRight;
AutoSize = true;
AutoSizeMode = GrowAndShrink;
WrapContents = true;
Now I set for each button the FlowBreak property to true, however the behavior I see is not the one I want, I want the FlowLayoutPanel to shrink to the width of the buttons,
Changing FlowDirection to UpToDown is not an option.
Anyone know why the AutoSize is not working?
this is the code.
//
//FlowLayoutPanel1
//
this.FlowLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.FlowLayoutPanel1.Controls.Add(this.FlowLayoutPanel3);
this.FlowLayoutPanel1.Location = new System.Drawing.Point(84, 77);
this.FlowLayoutPanel1.MinimumSize = new System.Drawing.Size(10, 10);
this.FlowLayoutPanel1.Name = "FlowLayoutPanel1";
this.FlowLayoutPanel1.Size = new System.Drawing.Size(308, 265);
this.FlowLayoutPanel1.TabIndex = 0;
//
//FlowLayoutPanel3
//
this.FlowLayoutPanel3.AutoSize = true;
this.FlowLayoutPanel3.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.FlowLayoutPanel3.Controls.Add(this.Button1);
this.FlowLayoutPanel3.Controls.Add(this.Button2);
this.FlowLayoutPanel3.Controls.Add(this.Button3);
this.FlowLayoutPanel3.Location = new System.Drawing.Point(127, 3);
this.FlowLayoutPanel3.MinimumSize = new System.Drawing.Size(10, 10);
this.FlowLayoutPanel3.Name = "FlowLayoutPanel3";
this.FlowLayoutPanel3.Size = new System.Drawing.Size(162, 87);
this.FlowLayoutPanel3.TabIndex = 1;
//
//Button1
//
this.FlowLayoutPanel3.SetFlowBreak(this.Button1, true);
this.Button1.Location = new System.Drawing.Point(3, 3);
this.Button1.Name = "Button1";
this.Button1.Size = new System.Drawing.Size(75, 23);
this.Button1.TabIndex = 0;
this.Button1.Text = "Button1";
this.Button1.UseVisualStyleBackColor = true;
//
//Button2
//
this.FlowLayoutPanel3.SetFlowBreak(this.Button2, true);
this.Button2.Location = new System.Drawing.Point(3, 32);
this.Button2.Name = "Button2";
this.Button2.Size = new System.Drawing.Size(75, 23);
this.Button2.TabIndex = 1;
this.Button2.Text = "Button2";
this.Button2.UseVisualStyleBackColor = true;
//
//Button3
//
this.Button3.Location = new System.Drawing.Point(3, 61);
this.Button3.Name = "Button3";
this.Button3.Size = new System.Drawing.Size(75, 23);
this.Button3.TabIndex = 2;
this.Button3.Text = "Button3";
this.Button3.UseVisualStyleBackColor = true;
It is a bug, it's been around for a very long time. The issue is that the layout engine for FlowLayoutPanel calculates the width of the first row wrong, including the width of the 2nd control, even though it got wrapped to the second row.
The workaround is silly but effective, add a dummy Panel with a Width of 0 after the 1st control. If you are doing this with the designer then drop it first and drag it in the right place, to the right of the 1st control. Then set its Margin to (0, 0, 0, 0) and Size to (0, 0) in the Properties window.
I don't believe the FlowLayoutPanel was designed to do what you're trying to do.
A TableLayoutPanel would probably be better suited. Add a TableLayoutPanel with a single column, and add each button to a row.
Edit: I found a hackish work around. After the first button, create a Panel with the size of 0,0 and the margin of 0,0. Make sure that FlowBreak is set to false.
Edit: You only need to create one panel, after the first button, not one for each.
Not a solution, but a workaround. It looks like you are trying to simulate behavior of TableLayoutPanel by using flow breaks in FlowLayoutPanel. Did you try using TableLayoutPanel instead? According to your screenshots in the comments, it should work perfectly for your needs.
Related
I'm fairly new to programming and this is my first Forms program.
I'm trying to place buttons inside a panel in a manner that they get automatically sorted by alphabetical order.
At first I was trying with a FlowLayoutPanel, which displayed the buttons with the correct size and placement, but not sorted by Alphabetical order:
With FlowLayoutPanel. Ideal Size and placement, but no sorting.
I also had a few problems while trying to automatically scale it to screen size.
After failing with a FlowLayoutPanel, I tried just a normal panel. It fixed all my previous problems, but would stretch the buttons when docked:
With a normal panel. Perfect sorting and scaling, but stretching.
Here is the code, if it matters:
Button modButton = new Button();
modButton.Location = new System.Drawing.Point(3, 3);
modButton.Name = skinName;
modButton.Size = new System.Drawing.Size(200, 200);
modButton.TabIndex = 0;
modButton.Text = skinName;
modButton.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
modButton.UseVisualStyleBackColor = true;
modButton.BackgroundImageLayout = ImageLayout.Zoom;
modButton.Dock = System.Windows.Forms.DockStyle.Left;
modButton.Click += new System.EventHandler(this.modButton_Click);
modButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText;
this.panel2.Controls.Add(modButton);
modList.Add(skinName);
And for the panel:
this.panel2.AutoScroll = true;
this.panel2.AutoSize = true;
this.panel2.BackColor = System.Drawing.SystemColors.Control;
this.panel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel2.Location = new System.Drawing.Point(0, 0);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(636, 450);
this.panel2.TabIndex = 7;
I have form in WinForms that looks like
this
I want the user to be able to resize the form. Buttons would stay the same size and datagridviews would grow when he does this.
Right now, datagridviews are colliding with buttons and It looks pretty ugly.
I want datagridviews to grow, but not collide with buttons.
I've tried many different combinations of code and It doesn't work like I wanted.
I want buttons to be between datagridviews.
Designer:
//
// dataGridView1
//
this.dataGridView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Location = new System.Drawing.Point(13, 60);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.RowTemplate.Height = 24;
this.dataGridView1.Size = new System.Drawing.Size(291, 326);
this.dataGridView1.TabIndex = 0;
//
// dataGridView2
//
this.dataGridView2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.dataGridView2.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView2.Location = new System.Drawing.Point(566, 60);
this.dataGridView2.Name = "dataGridView2";
this.dataGridView2.RowTemplate.Height = 24;
this.dataGridView2.Size = new System.Drawing.Size(284, 326);
this.dataGridView2.TabIndex = 1;
//
// button1
//
this.button1.Anchor = System.Windows.Forms.AnchorStyles.None;
this.button1.Location = new System.Drawing.Point(375, 93);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(121, 83);
this.button1.TabIndex = 2;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
//
// button2
//
this.button2.Anchor = System.Windows.Forms.AnchorStyles.None;
this.button2.Location = new System.Drawing.Point(375, 187);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(121, 83);
this.button2.TabIndex = 3;
this.button2.Text = "button2";
this.button2.UseVisualStyleBackColor = true;
//
// button3
//
this.button3.Anchor = System.Windows.Forms.AnchorStyles.None;
this.button3.Location = new System.Drawing.Point(375, 281);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(121, 83);
this.button3.TabIndex = 4;
this.button3.Text = "button3";
this.button3.UseVisualStyleBackColor = true;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(862, 398);
this.Controls.Add(this.button3);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Controls.Add(this.dataGridView2);
this.Controls.Add(this.dataGridView1);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.dataGridView2)).EndInit();
this.ResumeLayout(false);
Try a TableLayoutPanel. You can define 3 columns, the first one set to 50%, the second one to the width of your buttons (or set to AutoSize, initially set it to an absolute or percentage value, then place your buttons. One placed go back and change to autosize otherwise the column will shrink to nothing if there's nothing in the column) and the third to 50%. Then you'll need at least 3 rows, 1 row per button.
Put your first DataGridView in Cell 0,0 (Col 0, Row 0) and set RowSpan to 3. Put your second DataGridView in Cell 2,0 (Col 2, Row 0) and, again, set RowSpan to 3. Then in the middle column (col 1) put your 3 buttons, one in each row. You can remove anchoring at that point so the buttons float in the middle of the column. Set your datagridviews to DockStyle.Fill and you shouldn't have any issues with the DataGridRow overlapping the buttons.
Here's a couple of screenshots.
Use the Anchor Property to your Datagridview and buttons.
I need to add controls programmatically to a custom control and position them in a certain layout. I thought it would be easy enough create a replica at design time inside a panel and then use the generated code to build them in another panel at runtime.
The dimensions such as widths, height & size are not working as expected between runtime vs design time. Why is this?
Eg below has 2 design time panels. The panel on the left contains design time controls and the one on the right runtime controls.
this.dateTimePicker1.Size = new System.Drawing.Size(219, 26); sets the width = 219
However, at runtime dtp2.Size = new System.Drawing.Size(219, 26); is too long and I have to use dtp1.Width = 150; instead. Why 150 and not 219?
RunTime Control Code:
private void BuildControls()
{
//
// dateTimePicker1
//
DateTimePicker dtp1 = new DateTimePicker();
dtp1.Location = new System.Drawing.Point(21, 35);
dtp1.Name = "dateTimePicker1";
//dtp1.Size = new System.Drawing.Size(219, 26);
dtp1.Width = 150; //Not 219 as expected?
dtp1.TabIndex = 1;
panel2.Controls.Add(dtp1);
// dateTimePicker2
//
DateTimePicker dtp2 = new DateTimePicker();
dtp2.Location = new System.Drawing.Point(21, 108);
dtp2.Name = "dateTimePicker2";
dtp2.Size = new System.Drawing.Size(219, 26); //Copying design time is too wide
//dtp1.Width = 150;
dtp2.TabIndex = 2;
panel2.Controls.Add(dtp2);
}
DesignTime Control Code:
private void InitializeComponent()
{
this.panel1 = new System.Windows.Forms.Panel();
this.label1 = new System.Windows.Forms.Label();
this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker();
this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker();
this.label2 = new System.Windows.Forms.Label();
this.panel2 = new System.Windows.Forms.Panel();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.Controls.Add(this.dateTimePicker2);
this.panel1.Controls.Add(this.label2);
this.panel1.Controls.Add(this.dateTimePicker1);
this.panel1.Controls.Add(this.label1);
this.panel1.Location = new System.Drawing.Point(26, 36);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(288, 514);
this.panel1.TabIndex = 0;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(17, 21);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(87, 20);
this.label1.TabIndex = 0;
this.label1.Text = "Start Date:";
//
// dateTimePicker1
//
this.dateTimePicker1.Location = new System.Drawing.Point(21, 44);
this.dateTimePicker1.Name = "dateTimePicker1";
this.dateTimePicker1.Size = new System.Drawing.Size(219, 26);
this.dateTimePicker1.TabIndex = 1;
//
// dateTimePicker2
//
this.dateTimePicker2.Location = new System.Drawing.Point(21, 108);
this.dateTimePicker2.Name = "dateTimePicker2";
this.dateTimePicker2.Size = new System.Drawing.Size(219, 26);
this.dateTimePicker2.TabIndex = 3;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(17, 85);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(81, 20);
this.label2.TabIndex = 2;
this.label2.Text = "End Date:";
//
// panel2
//
this.panel2.Location = new System.Drawing.Point(450, 260);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(288, 290);
this.panel2.TabIndex = 1;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(850, 710);
this.Controls.Add(this.panel2);
this.Controls.Add(this.panel1);
this.Name = "Form1";
this.Text = "Form1";
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
this.ResumeLayout(false);
}
Your problem is with Autoscaling.
This code:
this.dateTimePicker1.Size = new System.Drawing.Size(219, 26);
May not imply that this.dateTimePicker1.Size is really 219 x 26. Why? Because of this line here, from .designer.cs:
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
After that line an in-memory scaling is performed. This scaling is executed on all child controls right after this line:
this.groupBox1.PerformLayout();
After that, this.dateTimePicker1.Size will change to something closer to 150 in width. You may also notice that designer code does not match what's displayed in the properties pane when control is selected.
Solution, Part 1
Add something to the form to cause a change in the designer file and save it. This will at cause .designer.cs code to match the screen DPI and you won't see any inconsistencies any more. It seems that your DPI setting is higher than the one used when creating the form - if this is accidental, correct your Windows DPI setting to 96 or 100%.
Solution, Part 2
Once your form designer matches your screen DPI, you will see that all the size and location properties have been changed and that there is a new value set on AutoScaleDimensions, write down this value because this is the dimension that matches your screen DPI.
Now, whenever you want your controls' locations and sizes to respect the screen DPI you have to place your control logic in something like this:
// Your referential DPI setting (96DPI in this case)
this.AutoScaleDimensions = new SizeF(6F, 13F);
// TODO: Place your code here
// Setting of your users
this.AutoScaleDimensions = this.CurrentAutoscaleDimensions;
This would cause whatever controls placed in between to be scaled to whatever DPI is currently on the screen.
Note that 6F, 13F are values most people have for 96 DPI setting (default 100% zoom in Windows). This is why I asked to write down your value so you can use that instead.
If you still don't find this obnoxious you can also read up this question which has extra info: Creating a DPI-Aware Application.
Important Note
I forgot to mention something - if you work in a team with source control software, take extra care because whenever you save something in designer it's going to alter every Size and Location to match your own setting (as explained above). This shouldn't cause problems but you should be always aware of this.
try changing
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
to
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
I'm creating a GUI in C# using WinForms.
I'm trying to position programaticaly created panels one below the other. As the content of these panel can vary depending on their content, I'm using Panel.AutoSize to let WinForms perform the correct resizing.
The problem is: if I'm using Panel.Height (or Panel.Size.Height) right after populating the Panel, the value returned is always my default value. The resizing do occur, as I can see when launching the app, but I just don't know when.
Here's a simplified version of what I'm doing:
this.SuspendLayout();
int yPos = 0;
foreach (String entry in entries)
{
Panel panel = new Panel();
panel.SuspendLayout();
panel.AutoSize = true;
panel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly;
panel.BackColor = System.Drawing.SystemColors.Window; // Allows to see that the panel is resized for dispay
panel.Location = new System.Drawing.Point(0, yPos);
panel.Size = new System.Drawing.Size(this.Width, 0);
this.Controls.Add(panel);
Label label = new Label();
label.AutoSize = true;
label.Location = new System.Drawing.Point(0, 0);
label.MaximumSize = new System.Drawing.Size(panel.Width, 0);
label.Text = entry;
panel.Controls.Add(label);
panel.ResumeLayout(false);
panel.PerformLayout();
yPos += panel.Height; // When breaking here, panel.Height is worth 0
yPos += label.Height; // This works perfectly, label.Height was updated according to the text content when breaking at that point
}
this.ResumeLayout(false);
this.PerformLayout();
So the real question is: How can I get the updated Panel.Size after adding controls to it, to get its proper height value?
Note: I know I can use the TextBox height, but I find it inelegant and impractical, as in my actual code there are more controls in the Panel and I need to use that panel height a few lines below.
What I beleive is happening is that the Size of the Panel will be determined when you do PerformLayout on its Parent. You can make it work like you are wanting by moving the panel's parent SuspendLayout / ResumeLayout code into the Loop.
int yPos = 0;
foreach (String entry in entries)
{
this.SuspendLayout();
Panel panel = new Panel();
panel.SuspendLayout();
panel.AutoSize = true;
panel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowOnly;
panel.BackColor = System.Drawing.SystemColors.Window; // Allows to see that the panel is resized for dispay
panel.Location = new System.Drawing.Point(0, yPos);
panel.Size = new System.Drawing.Size(this.Width, 0);
this.Controls.Add(panel);
Label label = new Label();
label.AutoSize = true;
label.Location = new System.Drawing.Point(0, 0);
label.MaximumSize = new System.Drawing.Size(panel.Width, 0);
label.Text = entry;
panel.Controls.Add(label);
panel.ResumeLayout(true);
this.ResumeLayout(true);
yPos += panel.Height; // When breaking here, panel.Height is worth 0
//yPos += label.Height; // This works perfectly, label.Height was updated according to the text content when breaking at that point
}
this.PerformLayout();
I have a flowlayout as follows:
I need to center all the controls on the form (In other words, let's say the form's width is 200. btnOpt1 to btnOpt4 should have their Left starting at 100 minus half of the button width, not 0.)
You can do it two ways but with some limitation of each one.
Using Anchor property
Using the layout control with help of Docking and Anchor properties.
Method 1: Anchor Property
Controls are anchored by default to the top left of the form which
means when the form size will be changed, their distance from the top
left side of the form will remain constant. If you change the control
anchor to bottom left, then the control will keep the same distance
from the bottom and left sides of the form when the form if resized.
Turning off the anchor in a direction will keep the control centred in
that direction when resizing.
Example :
public TestForm12()
{
InitializeComponent();
Button btn = new Button();
btn.Width = this.Width - 10;
btn.Height = 20;
btn.Left = (this.ClientSize.Width - btn.Width) / 2;
btn.Top = (this.ClientSize.Height - btn.Height) / 2;
btn.Text = "click me";
this.Controls.Add(btn);
btn.Anchor = AnchorStyles.None;
}
2. Using the layout control
Add TableLayout Control, Set it’s Dock property to Fill.
Add 1 Row with Size Type style Percent 100%
Add 3 Columns Column1(Size Type – Percent(100%)), Column2(Size Type – Absolute(200px)), Column3(Size Type – Percent(100%)).
Now Add Panel Control to Column2 and Set it’s Dock property to Fill
Add Buttons to this control and set their Size as you want and Set Their Anchor Property to AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top
Example - Designer.cs code snippet of the form.
private void InitializeComponent()
{
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.panel1 = new System.Windows.Forms.Panel();
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.tableLayoutPanel1.SuspendLayout();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 3;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 200F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel1.Controls.Add(this.panel1, 1, 0);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 1;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(284, 262);
this.tableLayoutPanel1.TabIndex = 0;
//
// panel1
//
this.panel1.Controls.Add(this.button2);
this.panel1.Controls.Add(this.button1);
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Location = new System.Drawing.Point(45, 3);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(194, 256);
this.panel1.TabIndex = 0;
//
// button1
//
this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.button1.Location = new System.Drawing.Point(3, 9);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(188, 23);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
//
// button2
//
this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.button2.Location = new System.Drawing.Point(3, 38);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(188, 23);
this.button2.TabIndex = 0;
this.button2.Text = "button1";
this.button2.UseVisualStyleBackColor = true;
//
// TestForm11
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 262);
this.Controls.Add(this.tableLayoutPanel1);
this.Name = "TestForm11";
this.Text = "TestForm11";
this.tableLayoutPanel1.ResumeLayout(false);
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button1;
Hope this help..
I'd go with TableLayoutPanel instead:
Put TableLayoutPanel on your form
Set dock style Fill to panel
Leave only one column inside panel
Create row for every button (and put buttons to table cells)
Set row size type Autosize
Set dock style Fill to every button, except last one
Set dock style Top to last button
BTW in your solution you should iterate over flowLayoutPanel controls instead of form controls. Also consider subtracting horizontal margin and padding from width:
foreach (Control control in flowLayoutPanel.Controls)
{
control.Size = new Size(flowLayoutPanel.Width - control.Margin.Horizontal,
control.Height);
}
But I advise you to use TableLayoutPanel instead.
I solved this by changing the margin values. I am adding my content to a panel though.
C#:
int horizontalMargin = (int)(0.5 * (this.containingPanelOrForm.Width - this.button.Width));
this.btnOptX.Margin = new Padding(horizontalMargin, 0, horizontalMargin, 0);
Or you can use Grid layout instead.
I´m not good in C# but you can also add a panel in flowlayoutpanel with the same width of flowlayoutpanel. Then you can add in the Panel created in running time the button you want and set the dock to left or right. As you wish. Let me show a example in VB.net and C# (used online converts)
VB.net
Dim btn As New Button
btn.Text = "Example"
btn.Name = "Button"
btn.Size = New Size(60,10)
Dim panel As New Panel
panel.Size = New Size(FlowLayoutPanel1.Width, 10) 'size of the flowlayoutpanel + height of button
btn.Dock = DockStyle.Right
FlowLayoutPanel1.Controls.Add(panel)
panel.controls.add(btn)
C#
Button btn = new Button();
btn.Text = "Example";
btn.Name = "Button";
btn.Size = new Size(60, 10);
Panel panel = new Panel();
panel.Size = new Size(FlowLayoutPanel1.Width, 10);
//size of the flowlayoutpanel + height of button
btn.Dock = DockStyle.Right;
FlowLayoutPanel1.Controls.Add(panel);
panel.controls.#add(btn);
Create empty Label with Name = lblEmpty and AutoSize = False. Put this control first in controls list in FlowLayoutPanel1, then add code below.
Example: Assuming three existing labels in FlowLayoutPanel1, the result should be lblEmpty, LabelExisting1, and LabelExisting2, in that order.
Dim MarginLabelEmpty As Integer = ((FlowLayoutPanel1.Width - (LabelExisting1.Width + LabelExisting2.Width)) / 2)
lblEmpty.Width = MarginLabelEmpty
I solved my problem by creating this code.
in your case with Button Controls, create 4 new labels with .Text=""(empty) and put each one at the beginning of each button, naming labels as follows: lblEmpty1, lblEmpty2, lblEmpty3, lblEmpty4.
Then Add the following code:
Dim MarginLeftbtnOptAll As Integer = ((FlowLayoutPanel1.Width - btnOpt1.Width) / 2)
lblEmpty1.AutoSize = False
lblEmpty1.Width = MarginLeftbtnOptAll
lblEmpty2.AutoSize = False
lblEmpty2.Width = MarginLeftbtnOptAll
lblEmpty3.AutoSize = False
lblEmpty3.Width = MarginLeftbtnOptAll
lblEmpty4.AutoSize = False
lblEmpty4.Width = MarginLeftbtnOptAll
This center button, increasing the width of the empty label according to the width of the FlowLayoutPanel1
Throwing the buttons directly to the form or a panel (not FlowLayoutPanel), and setting Anchor = Top (only Top) for all of them, they won't be centered but will always move proportional to the form's (or container's) sides when resizing.
Private Sub FlowLayoutPanel1_SizeChanged(sender As Object, e As EventArgs)` Handles FlowLayoutPanel1.SizeChanged
Dim TotalWidth As Integer = FlowLayoutPanel1.Controls.Count * button.Width
Dim LeftPadding As Integer = (FlowLayoutPanel1.Width - TotalWidth) / 2
Dim GapPadding As Integer = FlowLayoutPanel1.Controls.Count * 5
If TotalWidth <= FlowLayoutPanel1.Width Then
FlowLayoutPanel1.Padding = New Padding(LeftPadding - GapPadding, 0, 0, 0)
End If
End Sub