[英]How to adjust TableLayoutPanel to wrap content by height and weight? (dynamically)
I created a Form that I am going to use as pop-up.我创建了一个将用作弹出窗口的表单。
I need that this pop-up contains title, ProgressBar and percentage text.我需要这个弹出窗口包含标题、进度条和百分比文本。
So, for this purpose, I choose to use TableLayoutPanel
as a control in my Form.因此,为此,我选择在我的 Form 中使用TableLayoutPanel
作为控件。
All these UI elements are created in dynamically.所有这些 UI 元素都是动态创建的。 For test now I am using Label instead of real ProgressBar.为了测试,我现在使用 Label 而不是真正的 ProgressBar。
public partial class TestFormDeleteIt : Form
{
public TestFormDeleteIt()
{
InitializeComponent();
AutoSize = true;
var flp = CreateTableLayoutPanel();
Controls.Add(flp);
}
private Control CreateTableLayoutPanel()
{
// TableLayoutPanel Initialization
var panel = new TableLayoutPanel
{
ColumnCount = 2,
RowCount = 2,
Dock = DockStyle.Fill
};
//Adjust column size in percentage
panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 70F));
panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 30F));
//Adjust row size in percentage
panel.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
panel.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
//Fill content
panel.Controls.Add(
new Label()
{
Text = "state",
Dock = DockStyle.Fill
},
/*column*/ 0, /*row*/ 0);
panel.Controls.Add(
new Label()
{
Text = "ProgressBar",
Dock = DockStyle.Fill
},
/*column*/ 0, /*row*/ 1);
panel.Controls.Add(
new Label()
{
Text = "100%",
Dock = DockStyle.Fill
},
/*column*/ 1, /*row*/ 1);
return panel;
}
}
So, as you can see I create TableLayoutPanel
divided by rows and columns and for each view that it holds I set Dock = DockStyle.Fill
, because I don't want to hardcode a fixed size.因此,正如您所看到的,我创建了TableLayoutPanel
按行和列划分,并为它持有的每个视图设置Dock = DockStyle.Fill
,因为我不想对固定大小进行硬编码。
What am I expecting is that each UI element fills a Cell in the TableLayoutPanel and the parent Form itself will adjust its size by the TableLayoutPanel that holds all the other Controlss.我期望的是每个 UI 元素都填充 TableLayoutPanel 中的一个单元格,并且父窗体本身将通过包含所有其他 Controlss 的 TableLayoutPanel 调整其大小。
But actually I get this result:但实际上我得到了这个结果:
The Parent Form doesn't wrap content, it looks like it has fixed size and the TableLayoutPanel tries to fill the Form ClientArea.父窗体不包装内容,它看起来像固定大小,并且 TableLayoutPanel 尝试填充窗体 ClientArea。 I've set AutoSize = true;
我已经设置了AutoSize = true;
, but it has no visible affect. ,但它没有明显的影响。
What am I doing wrong?我究竟做错了什么?
EDIT编辑
Thanks, @Jimi now it looks like much better谢谢,@Jimi 现在看起来好多了
I also added我还加了
MinimumSize = new System.Drawing.Size(600, Height)
to TLP, but question is - as you can see each row has like min height.到 TLP,但问题是 - 正如您所看到的,每一行都有最小高度。 And it looks like space between each row.它看起来像每行之间的空间。 Why is it happens?为什么会发生?
EDIT2编辑2
I would like to notice that if I change this我想注意,如果我改变这个
panel.Controls.Add(
new Label()
{
Text = "state",
Dock = DockStyle.Fill
},
/*column*/ 0, /*row*/ 0);
to this:对此:
var label1 = new Label()
{
Text = "state",
Dock = DockStyle.Fill
};
panel.SetRow(label1, 0);
panel.SetColumn(label1, 0);
it doesn't work... What am I doing wrong?它不起作用......我做错了什么?
and here is my code now这是我的代码
public partial class TestFormDeleteIt : Form
{
public TestFormDeleteIt()
{
InitializeComponent();
AutoSize = true;
AutoSizeMode = AutoSizeMode.GrowAndShrink;
MinimumSize = new System.Drawing.Size(200, 0);
var flp = CreateTableLayoutPanel();
Controls.Add(flp);
}
private TableLayoutPanel CreateTableLayoutPanel()
{
// TableLayoutPanel Initialization
var panel = new TableLayoutPanel
{
ColumnCount = 2,
RowCount = 2,
Dock = DockStyle.Fill
};
//Adjust column size in percentage
panel.ColumnStyles.Clear();
panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 90F));
panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 10F));
//Adjust row size in percentage
panel.RowStyles.Clear();
panel.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
panel.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
//Fill content
panel.Controls.Add(
new Label()
{
Text = "state",
Dock = DockStyle.Fill
},
/*column*/ 0, /*row*/ 0);
panel.Controls.Add(
CreateProgressBar(),
/*column*/ 0, /*row*/ 1);
panel.Controls.Add(
new Label()
{
Text = "100%",
Dock = DockStyle.Fill
},
/*column*/ 1, /*row*/ 1);
panel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
panel.AutoSize = true;
return panel;
}
private Control CreateProgressBar() => new ProgressBar()
{
Visible = true,
Dock = DockStyle.Top
};
}
Problem is - that even if I set static width as 200 -> MinimumSize = new Size(200, 0)
in my Form, when I open it I see that it takes like 1000
.问题是 - 即使我将静态宽度设置为 200 -> MinimumSize = new Size(200, 0)
在我的表单中,当我打开它时,我看到它需要1000
。
Why is it happens?为什么会发生?
The scenario :场景:
How to proceed :如何进行:
The sequence of the operations will clearly determine the final result.该操作的顺序将明确判断最终结果。
PerformLayout()
method) Form 现在实际上不会做任何事情,因为它此时无法执行其布局(除非明确指示,使用PerformLayout()
方法)MinimumSize = new Size(200, 0)
, we define a minimum Width, but the Height dimension is free to grow and also shrink, here - setting 0
as value, means no restrictions ).我们设置了一个最小尺寸,限制了它的宽度,而不是它的高度(设置MinimumSize = new Size(200, 0)
,我们定义了一个最小宽度,但高度尺寸可以自由增长和收缩,这里 - 设置0
作为值, 表示没有限制)。SuspendLayout()
, position the new Control and ResumeLayou()
(without also performing the Layout of the child Controls, since this has just happened): at this point, the Form, instructed to AutoSize to its content, will calculate its PreferredSize
and then auto-size itself to the new content.现在,当 Control 被添加到 Controls 集合时,内部方法指示 ContainerControl 到SuspendLayout()
,定位新的 Control 和ResumeLayou()
(不执行子控件的布局,因为这刚刚发生):在这一点上,被指示根据其内容自动调整大小的表单将计算其PreferredSize
,然后根据新内容自动调整大小。TableLayoutPanel
is now set to Dock to the parent Container. TableLayoutPanel
现在设置为停靠到父容器。 The Container is already auto-sized to the size of the TableLayoutPanel
, so the TLP just fixes its anchors to the current Size of the Form. Container 已经自动调整到TableLayoutPanel
的大小,所以 TLP 只是将其锚点固定到 Form 的当前大小。The final Layout will be performed before the Form is shown: anyway, at this point, all the Controls involved are already sized and positioned as instructed.最终的 Layout 将在 Form 显示之前执行:无论如何,此时,所有涉及的 Controls 都已经按照指示调整了大小和位置。
Extra :额外的:
► The TableLayoutPanel's SetColumn() and SetRow() are called explicitly. ► TableLayoutPanel 的SetColumn()和SetRow()被显式调用。 The reason is partailly explained in the Remarks section of the two methods:原因在两种方法的备注部分有部分说明:
This method reapplies the table layout to all controls in the TableLayoutPanel.此方法将表格布局重新应用于TableLayoutPanel 中的所有控件。
In the current context, calling these methods is a plus .在当前上下文中,调用这些方法是加分项。 It's not strictly needed, because we just add Controls to the TLP, never remove one.它不是严格需要的,因为我们只是将控件添加到 TLP,从不删除。
But, when Controls are added to and removed from the TLP while the TLP is set to AutoSize to its content (this applies to the current context), the TLP won't actually perform the Layout as expected: the Cells will, in most cases (yes, not always...) maintain their original Size when a Control is removed (removed or disposed, the result is the same).但是,当将控件添加到 TLP 或从 TLP 中删除时,TLP 设置为其内容的 AutoSize(这适用于当前上下文),TLP 实际上不会按预期执行布局:在大多数情况下,单元格会(是的,并不总是......)当控件被移除(移除或处置,结果相同)时保持其原始大小。
Some notes on the matter are found here:可以在此处找到有关此问题的一些说明:
This code (different language but simple to read) can easily tested to reproduce the problem此代码(不同语言但易于阅读)可以轻松测试以重现问题
Dynamic TableLayoutPanel Controls Keep Border Width动态 TableLayoutPanel 控件保持边框宽度
► The ColumnStyles and RowStyles are cleared and new styles are added: ► 清除了ColumnStyles和RowStyles并添加了新样式:
- The original code actually adds new styles without removing the existing, default, ones: this can and will generate a layout problem in some situations. - 原始代码实际上添加了新样式而不删除现有的默认样式:这在某些情况下会并且会产生布局问题。 Some notes on the matter here:关于此事的一些说明:
Remove Row inside TableLayoutPanel makes a layout problem删除 TableLayoutPanel 内的 Row 会导致布局问题
Center multiple rows of controls in a FlowLayoutPanel在 FlowLayoutPanel 中居中多行控件
public partial class TestFormDeleteIt : Form
{
protected internal ProgressBar pBar = null;
protected internal Label lbl2 = null;
public TestFormDeleteIt()
{
InitializeComponent();
this.AutoSize = true;
this.AutoSizeMode = AutoSizeMode.GrowAndShrink;
this.MinimumSize = new Size(200, 0);
var tlp = CreateTableLayoutPanel();
tlp.AutoSizeMode = AutoSizeMode.GrowAndShrink;
tlp.AutoSize = true;
this.Controls.Add(tlp);
tlp.Dock = DockStyle.Fill;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Task.Run(() => UpdateProgress());
}
private TableLayoutPanel CreateTableLayoutPanel()
{
var panel = new TableLayoutPanel { ColumnCount = 2, RowCount = 2,
CellBorderStyle = TableLayoutPanelCellBorderStyle.Single
};
panel.ColumnStyles.Clear();
panel.RowStyles.Clear();
panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 70F));
panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 30F));
panel.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
panel.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
var lbl1 = new Label() { Text = "state", Dock = DockStyle.Fill };
panel.Controls.Add(lbl1);
panel.SetColumn(lbl1, 0);
panel.SetRow(lbl1, 0);
pBar = new ProgressBar() { Dock = DockStyle.Top };
panel.Controls.Add(pBar);
panel.SetColumn(pBar, 0);
panel.SetRow(pBar, 1);
lbl2 = new Label() { Text = "0%", Dock = DockStyle.Fill };
panel.Controls.Add(lbl2);
panel.SetColumn(lbl2, 1);
panel.SetRow(lbl2, 1);
return panel;
}
private async Task UpdateProgress()
{
for (int i = 1; i <= 100; i++) {
BeginInvoke(new Action(() => {
pBar.Value = i;
lbl2.Text = (i / 100.0).ToString("P");
}));
await Task.Delay(50);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.