How do I align controls in FlowLayoutPanel properly - c#

I am currently trying to play around with c#. I want to create a simple GUI containing (as minimal example) three labels. The first two should be aligned from top to buttom and the third one to the right of these two button.
I have this in a panel, like
Label p_LabelX = new Label();
p_LabelX.Text = "I am to the right";
FlowLayoutPanel p_ButtonLayout = new FlowLayoutPanel();
p_ButtonLayout.Width = 200;
Label p_Label1 = new Label();
p_Label1.Text = "I am upper left";
Label p_Label2 = new Label();
p_Label2.Text = "I am lower left";
p_ButtonLayout.Controls.Add(p_Label1);
p_ButtonLayout.Controls.Add(p_Label2);
FlowLayoutPanel p_MainLayout = new FlowLayoutPanel();
p_MainLayout.FlowDirection = FlowDirection.LeftToRight;
p_MainLayout.WrapContents = false;
p_MainLayout.AutoScroll = true;
p_MainLayout.Controls.Add(p_ButtonLayout);
p_MainLayout.Controls.Add(p_LabelX);
this.Controls.Add(p_MainLayout);
With this code, it kind of works, but I have some scrollbars and the mainlayout is not fullscreen within the panel. However, if I skip the AutoScroll line, the scrollbars are gone and the layout seems to be fullscreen, but the right button is not visible.
Any suggestions?

Related

Label not visible above ToolStrip

At runtime I add (and remove) several controls, as needed, to a main window which in Designer contains only a ToolStrip with some function buttons. In some cases I want to add an info label next to the toolStrip, but I cannot make it visible, ie. it is hidden below. The code for the label is straightforward
infoLabel = new Label();
infoLabel.AutoSize = true;
infoLabel.Location = new System.Drawing.Point(200, 10);
infoLabel.Size = new System.Drawing.Size(35, 13);
infoLabel.BackColor = System.Drawing.SystemColors.Control;
infoLabel.Font = new System.Drawing.Font("Arial", 13);
infoLabel.ForeColor = System.Drawing.Color.Black;
infoLabel.TabIndex = 1;
infoLabel.Text = "this is info";
infoLabel.BringToFront();
this.Controls.Add(infoLabel);
TabIndex and BringToFront I added as an act of desperation, it does not help. BTW the ToolStrip's TabIndex is 2, and its BackColor I changed to transparent.
However, when I placed a label over the ToolStrip in the Designer, it is visible (ie. on top). I analysed the code then but did not see anything different from what I am writing. What am I missing here?
I suggest calling infoLabel.BringToFront(); at the very end, at least after this.Controls.Add(infoLabel); you current code amended:
infoLabel = new Label();
...
infoLabel.Text = "this is info";
// First Add to this
this.Controls.Add(infoLabel);
// Only then we can make infoLabel be the topmost
// among all existing controls which are on this
infoLabel.BringToFront();
We create infoLabel, add it to this and finally make it topmost on this. To make code more readable I suggest something like this:
// Create a label on this
infoLabel = new Label() {
AutoSize = true,
Location = new System.Drawing.Point(200, 10),
Size = new System.Drawing.Size(35, 13),
BackColor = System.Drawing.SystemColors.Control,
Font = new System.Drawing.Font("Arial", 13),
ForeColor = System.Drawing.Color.Black,
TabIndex = 1,
Text = "this is info",
Parent = this // <- instead of this.Controls.Add(infoLabel);
};
// make infoLabel topmost among all controls on this
infoLabel.BringToFront();
Windows Forms controls do not have a property which you can use to set z-index of controls like one can do in CSS.
You'll need to call Parent.SetChildIndex(control, 0);. The control at the front of Controls collection is the topmost in z-order for a container control.

Dynamic label parent not working

I'm creating a chat program and for the chatbox i want there to be a whatsapp kind of style message layout. My way of doing it (probably not the best) is by creating a picturebox dynamically with my blue background picture in it and then adding a label , making the picturebox the parent and then overlay the message over the picture box. I'm using this bit of code :
private void CreateChatBox(int height, string message)
{
PictureBox pb = new PictureBox();
Label pbl = new Label();
pb.Name = height.ToString();
pbl.Text = message;
pbl.Name = height.ToString();
pb.Image = LocalChat.Properties.Resources.ChatBox_Test;
pb.SizeMode = PictureBoxSizeMode.StretchImage;
// set picturebox possitions and margins
pb.Left = 15;
pb.Top = 100;
pb.Width = 250;
pb.Height = 75;
tabPage.Controls.Add(pb);
//set label positions and margins
pbl.Parent = pb;
pbl.AutoSize = true;
pbl.Width = 200;
pbl.BackColor = Color.Transparent;
pbl.Location = new Point(1, 1);
// Add button click event Handler and add buttons and lables to the panel
tabPage.Controls.Add(pbl);
}
my problem is that i'm making the picturebox the parent of the label, yet the label will just sit on the very top left of the form and not inside the picturebox as i want. Am i not getting what parent should be doing?
or how do i get my label to be confined inside the picturebox?
You must remove your line of code
tabPage.Controls.Add(pbl);
at the end of the file
because after you set the parent of the label to the PictureBox you're setting its parent to the TabPage, again
When you use anyControl.Controls.Add(otherControl) you're setting the otherControl.Parent to anyControl
But i'll say that if you want that kind of control settings you should instead of dynamically creating and setting its control you could create an usercontrol and inside the usercontrol you would put the logic to the display of the message, and you could dinamically create the userControl and put it anywhere you would like

Why are Anchor properties not being honored within dynamically created nested components?

Let me begin by saying that I have not done a lot of Windows Forms development -- if there is an obvious mistake that I may be making, please don't hesitate to mention it.
Steps to reproduce my issue:
Create a new C# Windows Forms Project using VS 2010 or VS 2012
Using the VS Form Designer, add three FlowLayoutPanel components to the form
Set each FlowLayoutPanel to have the same height as the form and approximately 1/3 the width of the form
Position each FlowLayoutPanel so that they do not overlap each other horizontally and collectively consume approximately the entire area of the Form.
The leftmost FlowLayoutPanel is configured to have an Anchor of Top, Bottom, Left
The middle FlowLayoutPanel is configured to have an Anchor of Top, Bottom
The rightmost FlowLayoutPanel is configured to have an Anchor of Top, Bottom, Right
Add an event for Form_Shown:
private void Form1_Shown(object sender, EventArgs e)
{
Panel p = new Panel();
p.BorderStyle = BorderStyle.FixedSingle;
p.Width = 200;
p.Height = 100;
Label label1 = new Label();
label1.BorderStyle = BorderStyle.FixedSingle;
label1.Text = "Hello";
label1.Anchor = AnchorStyles.Top;
Label label2 = new Label();
label2.BorderStyle = BorderStyle.FixedSingle;
label2.Text = "World!";
label2.Anchor = AnchorStyles.Bottom;
p.Controls.Add(label1);
p.Controls.Add(label2);
middleFlow.Controls.Add(p); // add to the center most FlowLayoutPanel on Form1
}
The result seems to be that label1 is placed on top of label2, despite label2 being added second. Moreover, the anchor values seem to be ignored (as label1 is covering label2 when I intend for them to be anchored to the top and bottom of the Panel component, respectively)
If I use the Dock property instead of the Anchor property, the behavior is as desired. Why does the Anchor property not work in this situation?
Also, is there a way to anchor components to other components? I notice as I increase the size of my Form at runtime, horizontal "gaps" between panels appear. Ideally, I would like the panels to grow together, preventing any gaps/whitespace between them horizontally?
Thanks in advance for any suggestions or tips.
I'm still starting to learn c# and winforms, so the following may not be optimal but it does what you required.
Handled the labels with Dock=Top. Note that the labels are switched so that label1 is on top of label2, i.e., registering label1 last pushes down the already registered label2.
The positioning of the three panels is done without anchors and docks with an event handler for resize. Setting the size of the form after that raises a resize event. Colored to see the components.
using System;
using System.Drawing;
using System.Windows.Forms;
public class ThreePanel : Form {
FlowLayoutPanel leftFlow;
FlowLayoutPanel middleFlow;
FlowLayoutPanel rightFlow;
public ThreePanel(){
leftFlow = new FlowLayoutPanel() {
BackColor = Color.Yellow
};
middleFlow = new FlowLayoutPanel() {
BackColor = Color.LightGreen
};
rightFlow = new FlowLayoutPanel() {
BackColor = Color.LightBlue
};
this.Controls.Add(rightFlow);
this.Controls.Add(middleFlow);
this.Controls.Add(leftFlow);
this.Load += (s,e)=>Form1_Shown(s,e);
this.Resize += (s,e)=>{
int w=this.Width/3;
leftFlow.Width=middleFlow.Width
=rightFlow.Width=w;
leftFlow.Height=middleFlow.Height
=rightFlow.Height=this.Height;
leftFlow.Location=new Point(0,0);
middleFlow.Location=new Point(w,0);
rightFlow.Location=new Point(2*w,0);
};
this.Size = new Size(750,450);
}
private void Form1_Shown(object sender, EventArgs e)
{
Panel p = new Panel() {
BorderStyle = BorderStyle.FixedSingle,
Width = 200,
Height = 100,
BackColor = Color.Fuchsia,
};
Label label1 = new Label() {
BorderStyle = BorderStyle.FixedSingle,
Text = "Hello",
Dock = DockStyle.Top
};
Label label2 = new Label() {
BorderStyle = BorderStyle.FixedSingle,
Text = "World!",
Dock = DockStyle.Top
};
p.Controls.Add(label2);
p.Controls.Add(label1);
// add to the center most FlowLayoutPanel on Form1
middleFlow.Controls.Add(p);
}
public static void Main()
{
Application.Run(new ThreePanel());
}
}
I would expect exactly the behaviour that you mentioned.
The Anchor property only tells the parent container that the label should be sticked
to the parent. In your case AnchorStyles.Top means stick the label to the top and leave it there if the parent moves or resizes.
You did not specify dimensions or positions for the labels, so both overlapp.
The z-order of the controls is created implicitly from the order when added to middleFlow.Controls. You can check this using VS forms designer. Select "Bring to Front" or "Send to Back" and watch how the x.designer.cs changes.
Why it is in reverse order is one of the little .net secrets. The workaround is to change the order. Sometimes it is easier to do it manually than in the designer.

Any idea why my usercontrol isn't centering in my tabcontrol?

I'm a little confused as to why this isn't working, since I had it working in a prototype and the only big difference I think is that I use a custom TabItem and UserControl instead of the default ones. I'm trying to get the usercontrol that appears to be centered in the tab window, but it seems to be aligned left.
You hand this method the usercontrol you want to use and it formats it and sticks it in the tabcontrol. In a test solution I did of this earlier, setting scroll's horizontal and vertical alignment to stretch fixed this, but it's not working in this case. Is there some other setting or something else somewhere that would override this?
public void CreateNewTab(UserControlGeneric new_user_control, string tab_header)
{
//TabItem tab = new TabItem();
TabItemIndexed tab = new TabItemIndexed();
//The scrollviewer is created/setup to make sure the usercontrol gets scroll bars if the window if ever made smaller than the usercontrol
ScrollViewer scroll = new ScrollViewer();
//How you programatically set a scrollviewer's height and width to be "Auto"
scroll.Height = Double.NaN;
scroll.Width = Double.NaN;
scroll.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
scroll.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
scroll.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
scroll.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
scroll.Content = new_user_control;
tab.Content = scroll;
tab.Header = tab_header;
//If there aren't any tabs, then hide the "No Workspaces Open" notice (Since we're adding a tab)
if (!tabControl_main.HasItems) label_no_workspaces_open.Visibility = System.Windows.Visibility.Hidden;
tabControl_main.Items.Add(tab);
tabControl_main.SelectedItem = tab;
}

flowlayout control keeps adding control in the wrong direction in winforms

I have a flowlayout control in winforms, i have set its flow direction to TopDown but it keeps adding controls from left to right, autoscroll is also set to true.
flowLayoutPanel1.Controls.Clear();
Label labelInput = new Label();
ListBox listBoxNewInput = new ListBox();
//Initialize label's property
labelInput.Text = " #" + Convert.ToInt32(sequence);
labelInput.AutoSize = true;
//Initialize textBoxes Property
listBoxNewInput.HorizontalScrollbar = false;
listBoxNewInput.Items.Add(efforts);
//Add the newly created text box to the list of input text boxes
inputTextBoxesList.Add(listBoxNewInput);
//Add the labels and text box to the form
flowLayoutPanel1.FlowDirection = FlowDirection.TopDown;
flowLayoutPanel1.Controls.Add(labelInput);
flowLayoutPanel1.FlowDirection = FlowDirection.TopDown;
flowLayoutPanel1.Controls.Add(listBoxNewInput);
Set the WrapContents property of the flowLayoutPanel1 to false, it will not allow to move those controls on the right if they don't fit. In order to be able to scroll clipped content you can set AutoScroll property to true
Here is the code:
flowLayoutPanel1.FlowDirection = FlowDirection.TopDown;
flowLayoutPanel1.WrapContents = false;
flowLayoutPanel1.AutoScroll = true;
flowLayoutPanel1.Controls.Add(labelInput);
flowLayoutPanel1.Controls.Add(listBoxNewInput);

Categories