I create a TableLayoutPanel where I want to add two buttons one next to other so I try:
First I create panel as:
var pnlButtons = new TableLayoutPanel
{
Name = "pnlButtons",
AutoSize = true,
AutoSizeMode = AutoSizeMode.GrowAndShrink,
Dock = DockStyle.Bottom,
RowCount = 1,
TabIndex = 1
};
pnlButtons.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
pnlButtons.ColumnStyles.Add(new ColumnStyle());
pnlButtons.RowStyles.Add(new RowStyle());
pnlButtons.HandleCreated += new EventHandler(pnlButtons_Created);
this.Controls.Add(pnlButtons);
Then I add buttons in event handler:
private void pnlButtons_Created (object sender, EventArgs e)
{
var pnl = (TableLayoutPanel)sender;
var btnSetAmount = new Button
{
Text = "Set Amounts",
Name = "btnSetAmount",
Anchor = AnchorStyles.Top | AnchorStyles.Right,
TabIndex = 0,
UseVisualStyleBackColor = true
};
pnl.Controls.Add(btnSetAmount);
var btnCancel = new Button
{
Text = "Cancel",
Name = "btnCancel",
Anchor = AnchorStyles.Top | AnchorStyles.Left,
TabIndex = 1,
UseVisualStyleBackColor = true
};
pnl.Controls.Add(btnCancel);
}
But when I run it I see something like this:
It is in a different row. How can I do in order to set in the same row? Regards
Update: after comments above now it show it like:
The TableLayoutPanel has an override on the Controls collection that allows you to specify the column and row:
pnl.Controls.Add(btnSetAmount, 0, 0);
pnl.Controls.Add(btnCancel, 1, 0);
Related
I trying to build a method to draw my form dynamically, this method receives a list of questions, from this we draw a form and show each question (label) and an option (yes/no - radio buttons).
I can add each control created before in my Forms.Controls, but when the form opens, just one question is rendered passing a list with more than 20 questions. Why? Did I forget to do something?
This method builds all my components to the form based on my list of questions.
private void BuildComponents(List<Question> properties)
{
this.propertyList = new List<System.Windows.Forms.Control>();
for (int i = 0; i < properties.Count; i++)
{
var newLabel = new System.Windows.Forms.Label
{
AutoSize = true,
Location = new System.Drawing.Point(13 + i + 5, 13),
Name = properties[i].Label,
Size = new System.Drawing.Size(699, properties[i].Description.Length),
TabIndex = i,
Text = properties[i].Description,
};
var newYesRadioButton = new System.Windows.Forms.RadioButton
{
AutoSize = true,
Location = new System.Drawing.Point(13 + i + 5, 34),
Name = "radioButton" + i + 1,
Size = new System.Drawing.Size(52, 21),
TabIndex = i + 1,
TabStop = true,
Text = "Sim",
UseVisualStyleBackColor = true
};
var newNoRadioButton = new System.Windows.Forms.RadioButton
{
AutoSize = true,
Location = new System.Drawing.Point(71 + i + 5, 34),
Name = "radioButton" + i + 2,
Size = new System.Drawing.Size(55, 21),
TabIndex = i + 1,
TabStop = true,
Text = "Não",
UseVisualStyleBackColor = true
};
propertyList.Add(newLabel);
propertyList.Add(newYesRadioButton);
propertyList.Add(newNoRadioButton);
};
}
This method initializes my form and add all properties built in this.Controls
private void InitializeComponent()
{
this.BuildComponents(questions);
foreach (var property in propertyList)
{
this.Controls.Add(property);
}
}
I would recommend you to use FlowLayoutPanel and UserControls. With FlowLayoutPanel you can put usercontrols one after another and you dont need to deal with the location property.
In addition, you should not change InitializeComponent..
Actually, you dont need to touch the code in the designer file!
I have set this flowLayoutPanel, the controls inside arrange well, till the last arrives to the bottom border of the panel, then the controls start arranging on the right side (forming another column) keepping the vertical flow. I just want one column.
this.panel.Anchor =
((System.Windows.Forms.AnchorStyles)
(((System.Windows.Forms.AnchorStyles.Top |
System.Windows.Forms.AnchorStyles.Bottom)| System.Windows.Forms.AnchorStyles.Right)));
this.panel.AutoScroll = true;
this.panel.BorderStyle = BorderStyle.None;
this.panel.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
this.panel.Location = new System.Drawing.Point(0, 184);
this.panel.Name = "myPanel";
this.panel.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.panel.Size = new System.Drawing.Size(300, 371);
this.panel.TabIndex = 9;
Use
this.panel.FlowDirection = System.Windows.Forms.FlowDirection.LeftToRight;
instead of
this.panel.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
if you want only one column than please add below code to your application just after control added to your flowlayoutpanel
this.panel.SetFlowBreak(<<YOUR_ADDED_CONTROL_NAME>>, true);
Example
Button btn1 = new Button();
btn1.Text = "TEST";
btn1.Height = 30;
btn1.Width = 100;
this.panel.Controls.Add(btn1);
this.panel.SetFlowBreak(btn1, true);
I have a panel and 3 labels like so
----------
| Label1 |
| Label2 |
| Label3 |
----------
I want 33% of the panel to be label 1,2, and 3 so that they are equally distributed. Should I just use a TableLayoutPanel to accomplish this, the reason I am using Panel is because I need each set of 3 labels logically in blocks and I will have thousands of them.
The code I used so far to accomplish this is as follows
panel[0] = new Panel {
BackColor = Color.White,
Dock = DockStyle.Fill
};
label2[0] = new Label {
Text = "[label2]",
Dock = DockStyle.Fill,
AutoSize = false,
TextAlign = ContentAlignment.MiddleCenter
};
panel[0].Controls.Add(label2[0]);
label3[0] = new Label {
Text = "[label3]",
Dock = DockStyle.Bottom,
AutoSize = false,
TextAlign = ContentAlignment.BottomCenter
};
panel[0].Controls.Add(label3[0]);
label1[0] = new Label {
Text = "[label1]",
Dock = DockStyle.Top,
AutoSize = false,
TextAlign = ContentAlignment.TopCenter
};
panel[0].Controls.Add(label1[0]);
Right now my current effect is Label2 is slightly bigger than label1 and 3. For my purposes this effect was sort of nice for my purposes but on lower resolutions such as around 1024*768 Label 2 completely disappears or becomes way too small so the inverse happens. I don't understand exactly why this is happening nor do I understand how to distribute them evenly using a standard Panel. I am using thousands of these and I already have these inside a TableLayoutPanel so I didn't think it would be a good idea to make a bunch of TableLayoutPanels inside of TableLayoutPanels as I figure that would be overkill. What is a simple way to distribute 3 Labels equally in a regular Panel? After all I have TextAlign middle bottom top, why can't I use them to accomplish what I am doing since it is only 3 labels?
Hi CodeCamper you can set Anchor of panel to all,and labels to right and left,then u can try this.
private void Form1_Load(object sender, EventArgs e)
{
if (panel1.Height % 3 == 0)
{
SetLabels();
}
else
{
while (panel1.Height % 3 != 0)
{
panel1.Height++;
}
SetLabels();
}
}
private void SetLabels()
{
panel1.Controls["label1"].Location = new Point(1, 1);
panel1.Controls["label1"].Height = (panel1.Height / 3);
panel1.Controls["label1"].Width = panel1.Width;
label1.BackColor = Color.Red;
panel1.Controls["label2"].Location = new Point(1, label1.Height);
panel1.Controls["label2"].Height = label1.Height;
panel1.Controls["label2"].Width = panel1.Width;
label2.BackColor = Color.Purple;
panel1.Controls["label3"].Location = new Point(1, label2.Height + label1.Height);
panel1.Controls["label3"].Height = label1.Height;
panel1.Controls["label3"].Width = panel1.Width;
label3.BackColor = Color.Beige;
}
and all labels AutoSize property set to false.
Set label1 dock to top and label3 dock to bottom.
Then set label2 dock to fill autosize to false and textalign to MiddleLeft
EDIT:
set label.Tag to "makemecentered"
and add this to SizeChangedEvent of a Panel:
foreach (Label lab in (sender as Panel).Controls)
if (lab.Tag != null && lab.Tag.ToString() == "makemecentered")
lab.Top = (int)(sender as Panel).Height / 2 - lab.Height / 2;
EDIT 2:
I really don't know if my ability to read has gone... you wanted to set each of the labels to 33% so
set autosize of the labels to false
set desired textaligns
add panel SizeChanged event
private void panel1_SizeChanged(object sender, EventArgs e)
{
foreach (Label lab in (sender as Panel).Controls)
lab.Height = (int) (sender as Panel).Height/3;
}
and raise it on form create
This is my last edit, promise!
I'm trying to create a GroupBox, add a Grid (or StackPanel) to it then put some TextBlocks on it, all during runtime. This is what i've tried
GroupBox groupBox1 = new GroupBox();
Grid grid1 = new Grid();
groupBox1.Width = 85;
groupBox1.Height = 60;
grid1.Height = 85;
grid1.Width = 60;
groupBox1.Content = grid1.Children.Add(textBlock1);
groupBox1.Margin = new Thickness(50, 50, 0, 0);
mainWindow.canvas.Children.Add(groupBox1);
But all I get is a groupbox with a thick white border with nothing in it.
As far as I can see a Grid.Children.Add returns an int and that's not what you want to set the content of the groupBox1 to.
An untested idea from me as a non WPF expert is to set the grid as the Content of your groupbox.
grid1.Children.Add(textBlock1);
groupBox1.Content = grid1;
For simple checkboxes i used this code :
var container = new FlowLayoutPanel
{
FlowDirection = FlowDirection.TopDown,
Dock = DockStyle.Fill
};
myGroupBox.Controls.Add(container);
foreach (var myText in textList)
{
var checkBox = new CheckBox
{
Text = myText
};
container.Controls.Add(checkBox);
}
Of course the foreach statement is just for the example :)
I have a split container on panel 1 I have added a groupbox, in that groupbox is a flowcontrol which has dynamic number of textboxes, i have set both the groupbox and flowcontrol to dockstyle to fill.
In code i have also set the textboxes to dock style to fill, but they wont resize when i move the splitter, while the parent flowcontrol does resize.
Label labelInput = new Label();
TextBox listBoxNewInput = new TextBox();
listBoxNewInput.Name = ce.ToString();
labelInput.AutoSize = true;
labelInput.Font = new Font(labelInput.Font, FontStyle.Bold);
listBoxNewInput.Multiline = true;
// Add vertical scroll bars to the TextBox control.
listBoxNewInput.ScrollBars = ScrollBars.Vertical;
// Allow the RETURN key in the TextBox control.
listBoxNewInput.AcceptsReturn = true;
// Allow the TAB key to be entered in the TextBox control.
listBoxNewInput.AcceptsTab = true;
// Set WordWrap to true to allow text to wrap to the next line.
listBoxNewInput.WordWrap = true;
listBoxNewInput.Text = ts.ToString();
//listBoxNewInput.Width = 150;
listBoxNewInput.MinimumSize = new Size(200,150);
listBoxNewInput.MaximumSize = new Size(1000, 150);
listBoxNewInput.Dock = DockStyle.Fill;
listBoxNewInput.TextChanged += new EventHandler(listBoxNewInput_TextChanged);
//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.Controls.Add(labelInput);
flowLayoutPanel1.Controls.Add(listBoxNewInput);
if i try to put controls directly in to spliter panel 1 only the first two controls appear, which do resize when i move the splitter
splitContainer1.Panel1.Controls.Add(labelInput); splitContainer1.Panel1.Controls.Add(listBoxNewInput);
->if the controls when i put them in flow control resize, when i move the splitter that would be good
OR
->All controls appear when i put them directly into the splitter panel 1
Based on your comments and what I think you are trying to accomplish, I think you need to replace the FlowLayoutPanel with a TableLayoutPanel because it sounds like you are just stacking one TextBox below another.
Create a TableLayoutPanel with 1 column and 1 row.
Here is a working example:
tableLayoutPanel1.AutoScroll = true;
tableLayoutPanel1.GrowStyle = TableLayoutPanelGrowStyle.AddRows;
tableLayoutPanel1.RowStyles.Clear();
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 150));
for (int i = 0; i < 4; i++) {
AddTextBox("TextBox #" + i.ToString());
}
private void AddTextBox(string info) {
TextBox tx = new TextBox();
tx.Multiline = true;
tx.Text = info;
tx.ScrollBars = ScrollBars.Vertical;
tx.WordWrap = true;
tx.Height = 150;
tx.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right;
tableLayoutPanel1.Controls.Add(tx);
}
Instead of docking, I set the height of the TextBox and then I set the Anchors so that when the SplitPanel resizes, the TextBoxes resize appropriately.