英文:
C# WinForms TableLayoutPanel acts weird when adding two elements on one row
问题
想要在WinForms的TableLayoutPanel中使用以下方式:每行有两列,第一列占80%,第二列占20%。第一列有一个TextBox,第二列有一个按钮。我已经制作了一个按钮,将这样的行添加到表格中,但正如视频中所见,这看起来非常糟糕。在此之前,我使用了FlowLayoutPanel,但被建议改用TableLayoutPanel。这是演示视频: https://youtu.be/4hcBAeWCtTQ | 这是添加按钮的代码:
private void manual_packages_add_Click(object sender, EventArgs e) {
static Size MulSize(Size sz, Size accord, int percent) {
static float Percent(float n, int p) => n * (p / 100);
SizeF origF = (SizeF)sz;
SizeF accordF = (SizeF)accord;
origF.Height += Percent(accordF.Height, percent);
return origF.ToSize();
}
TextBox tbx = new() {
Name = $"manual_packages_pkg{manual_nextPkgTbxIndex++}",
Size = new((int)Math.Round(manual_packages_list.ColumnStyles[0].Width),
(int)Math.Round(manual_packages_list.RowStyles[0].Height)),
MaxLength = 34,
BorderStyle = BorderStyle.Fixed3D,
};
Button rm = new() { Name = $"manual_packages_rm{manual_nextPkgTbxIndex}",
Text = "i suffer 💀💀💀💀💀" };
manual_packages_list.Controls.Add(tbx, 0, manual_packages_list.RowCount++);
manual_packages_list.Controls.Add(rm, 1, manual_packages_list.RowCount++);
// sizing
Control? container = tbx.Parent;
bool firstIter = true;
while (true) {
container = firstIter ? container : container.Parent;
if (container == null)
break;
container.Size = MulSize(container.Size, tbx.Size, 100);
firstIter = false;
}
}
英文:
Wanna use WinForms' TableLayoutPanel in such way: Each row has two columns, one takes 80%, the second one 20%. On the first column, there's a TextBox, on the second: a button. I have made a button that adds such row to the table, but, as seen in the video, this goes awful. Before that i used FlowLayoutPanel, but was advised to use Table- instead. Here's a demo video: https://youtu.be/4hcBAeWCtTQ | And here's the Add button code:
private void manual_packages_add_Click(object sender, EventArgs e) {
static Size MulSize(Size sz, Size accord, int percent) {
static float Percent(float n, int p) => n * (p / 100);
SizeF origF = (SizeF)sz;
SizeF accordF = (SizeF)accord;
origF.Height += Percent(accordF.Height, percent);
return origF.ToSize();
}
TextBox tbx = new() {
Name = $"manual_packages_pkg{manual_nextPkgTbxIndex++}",
Size = new((int)Math.Round(manual_packages_list.ColumnStyles[0].Width),
(int)Math.Round(manual_packages_list.RowStyles[0].Height)),
MaxLength = 34,
BorderStyle = BorderStyle.Fixed3D,
};
Button rm = new() { Name = $"manual_packages_rm{manual_nextPkgTbxIndex}",
Text = "i suffer 💀💀💀💀💀" };
manual_packages_list.Controls.Add(tbx, 0, manual_packages_list.RowCount++);
manual_packages_list.Controls.Add(rm, 1, manual_packages_list.RowCount++);
// sizing
Control? container = tbx.Parent;
bool firstIter = true;
while (true) {
container = firstIter ? container : container.Parent;
if (container == null)
break;
container.Size = MulSize(container.Size, tbx.Size, 100);
firstIter = false;
}
}
Initial state
Clicked the Add button 3 times
Clicked the Add button 4 times and more
I tried removing the sizing (which didn't result in any good), i coded it to align everything, but it didn't work.
答案1
得分: 1
你应该已经做的是在TableLayoutPanel
中显示边框,然后你会发现你实际上每行只添加了一个控件,而不是两个。问题出在这里:
manual_packages_list.Controls.Add(tbx, 0, manual_packages_list.RowCount++);
manual_packages_list.Controls.Add(rm, 1, manual_packages_list.RowCount++);
你在这两行都增加了manual_packages_list.RowCount
,所以每个控件都会被添加到不同的行。如果你希望这两个控件都添加到同一行,那么你不能在添加第一个控件后再增加行数。至少要从第一行中去掉增量:
manual_packages_list.Controls.Add(tbx, 0, manual_packages_list.RowCount);
manual_packages_list.Controls.Add(rm, 1, manual_packages_list.RowCount++);
话虽如此,我认为这并不是真正的做法。我认为你应该从第1行开始计数,然后当你想要添加控件到第二行时,你应该先增加行数,然后再添加这两个控件。实际上应该是这样的:
manual_packages_list.Controls.Add(tbx, 0, ++manual_packages_list.RowCount);
manual_packages_list.Controls.Add(rm, 1, manual_packages_list.RowCount);
你(打算)这样做的方式,你已经有了一个空行,没有任何控件,然后你在该行添加控件,然后再添加另一空行。更合理的方式是默认情况下不要有空行,只有在需要时才添加一个空行,然后在它上面添加控件。
英文:
What you should have done is displayed the borders in the TableLayoutPanel
and you would have seen that you were actually adding only one control per row, not two. The issue is here:
manual_packages_list.Controls.Add(tbx, 0, manual_packages_list.RowCount++);
manual_packages_list.Controls.Add(rm, 1, manual_packages_list.RowCount++);
You are incrementing manual_packages_list.RowCount
in both of those lines, so every control will be added to a different row. If you expect both those controls to be added to the same row then you can't increment the row count after adding the first control. At the very least, remove the increment from the first line:
manual_packages_list.Controls.Add(tbx, 0, manual_packages_list.RowCount);
manual_packages_list.Controls.Add(rm, 1, manual_packages_list.RowCount++);
That said, I don't think that's really the way to do it. I would think that you would be starting with a row count of 1 and then, when you want to add controls to a second row, you would increment the row count first, then add the two controls. That would actually look like this:
manual_packages_list.Controls.Add(tbx, 0, ++manual_packages_list.RowCount);
manual_packages_list.Controls.Add(rm, 1, manual_packages_list.RowCount);
The way you're (intending to be) doing it, you already have an empty row in the table with no controls in it, then you add controls to that row, then you add another empty row. It would make more sense to not have the empty row by default and only add an empty row when you need one, then add controls to it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论