C# 使用生成的控件正确设计(最佳位置)此winform面板

C# 使用生成的控件正确设计(最佳位置)此winform面板,c#,winforms,C#,Winforms,我正在尝试自动生成并在面板(panelMetaData)上很好地显示这些控件。 所有内容都显示在屏幕上,并在一定程度上对齐,而一些标签文本覆盖了其他标签文本等。我该如何将此控件正确定位?我遗漏了什么位置逻辑 panelMetaData是使用工具箱中的属性(拖放)添加的,这些属性包括,Dock:Fill,AutoSize:True和AutoScroll:True 这是创建控件并将其放置在面板中的方法:(我删除了一些代码以使读取尽可能容易) 在阅读答案之前,最好考虑: 您可以使用带有2列的控件更

我正在尝试自动生成并在面板(panelMetaData)上很好地显示这些控件。 所有内容都显示在屏幕上,并在一定程度上对齐,而一些标签文本覆盖了其他标签文本等。我该如何将此控件正确定位?我遗漏了什么位置逻辑

panelMetaData
是使用工具箱中的属性(拖放)添加的,这些属性包括,
Dock:Fill
AutoSize:True
AutoScroll:True

这是创建控件并将其放置在面板中的方法:(我删除了一些代码以使读取尽可能容易)


在阅读答案之前,最好考虑:

  • 您可以使用带有2列的控件更简单地布局控件
  • 此外,要显示验证消息,您可以使用,并使用错误提供程序方法为控件设置错误或清除错误
但我在你的代码中看到的错误逻辑是:


当您将
AutoSize
属性设置为
true
,然后将它们添加到
panelMetaData中时,您没有为标签设置任何文本。控件
会使它们的大小
(0,0)
。然后您使用标签的
宽度
来定位控件,由于标签的
宽度
0
,控件将显示
位置。在阅读答案之前,最好考虑:

  • 您可以使用带有2列的控件更简单地布局控件
  • 此外,要显示验证消息,您可以使用,并使用错误提供程序方法为控件设置错误或清除错误
但我在你的代码中看到的错误逻辑是:



当您将
AutoSize
属性设置为
true
,然后将它们添加到
panelMetaData中时,您没有为标签设置任何文本。控件
会使它们的大小
(0,0)
。然后将标签的
Width
用于控件的位置,由于标签的
Width
0
,控件将显示为
位置。X=0

我注意到您使用
控件.Width
属性作为下一个控件位置的基础。您应该真正使用
Control.Right
属性来实现此目的。

我注意到您使用
Control.Width
属性作为下一个控件位置的基础。为此,您应该真正使用
Control.Right
属性。

您可以将a与2列一起使用,也可以显示验证消息。您可以使用a来显示可能不相关的验证消息,但移动行
panelMetaData.Controls.AddRange(labels.ToArray())在<代码>之外loop@RezaAghaei谢谢调查@伊凡斯托夫:谢谢,我忘了!:)将文本框与最大标签对齐!因此,首先放置标签(当然还有它们的文本!),找到它们的最大正确值,然后将文本框放在那里!您可以将a与2列一起使用,也可以显示验证消息。您可以使用a,但行
panelMetaData.Controls.AddRange(labels.ToArray())在<代码>之外loop@RezaAghaei谢谢调查@伊凡斯托夫:谢谢,我忘了!:)将文本框与最大标签对齐!因此,首先放置标签(当然还有它们的文本!),找到它们的最大正确值,然后将文本框放在那里!我会试试你说的,谢谢。我还推荐了label.text,它在实际代码中是有效的。假设我有两列,如何将其替换为?第一栏?谢谢<代码>panelMetaData.Controls.AddRange(txtboxs.ToArray())
我认为@IvanStoev的答案是正确的(如果您在将标签添加到面板之前设置了标签的文本),您应该使用
.Right
.Left
+
.Width
;但我认为您应该使用
TableLayoutPanel
和tableLayoutPanel1.Controls.Add方法接受行和单元格索引。我将试用您所说的,谢谢。我还推荐了label.text,它在实际代码中是有效的。假设我有两列,如何将其替换为?第一栏?谢谢<代码>panelMetaData.Controls.AddRange(txtboxs.ToArray())
我认为@IvanStoev的答案是正确的(如果您在将标签添加到面板之前设置了标签的文本),您应该使用
.Right
.Left
+
.Width
;但我认为您应该使用
TableLayoutPanel
和tableLayoutPanel1.Controls.Add方法接受行和单元格索引。实际上,这仍然是一个更好的方法,可以创建一个难看的锯齿状外观。@TaW正确,但由于我已经看到两种样式都要使用,我假设OP正在尝试获得锯齿状外观,而TableLayoutPanel是专为您所谈论的内容而设计的。谢谢。因为这是我问题的答案,但正如你们都建议的,表格布局更好。所以我就用了它。实际上,这是一个更好的方法,它仍然可以创造一个丑陋的锯齿状外观。@TaW是正确的,但因为我已经看到了两种样式的使用,我认为OP是在尝试获得锯齿状外观,而TableLayoutPanel是专门为您所说的内容而设计的。谢谢。因为这是我问题的答案,但正如你们都建议的,表格布局更好。所以我用了这个。
private void createAttributePanelControls()
{

    txtboxes = new List<Control>();
    labels = new List<Control>();
    valLabel = new List<Control>();
    combobox = new List<Control>();
    datetimetxtboxes = new List<Control>();

    int stringcnt = 0;
    int datecnt = 0;
    int listcnt = 0;

    for (int i = 0; i < attributes.Length; i++)
    {
        Attribute attribute = attributes[i];

        labels.Add(CreateLabel(attribute.getDisplayName(), i, new Point(26, 56 + (i * 30))));
        panelMetaData.Controls.AddRange(labels.ToArray());


        switch (attribute.getType())
        {
            case DocAttribute.STRING:

                txtboxes.Add(CreateTextBox(attribute.getDisplayName(), i, new Point(labels[i].Width, labels[i].Top - 3)));
                 valLabel.Add(CreateValidationLabel(attribute.getDisplayName(), i, new Point(txtboxes[stringcnt].Width, labels[i].Top - 3)));  
                stringcnt++;
                break;
            case DocAttribute.DATE:

                datetimetxtboxes.Add(CreateDateTimePicker(attribute.getDisplayName(), i, new Point(labels[i].Widt, 56 + (i * 30))));
                 valLabel.Add(CreateValidationLabel(attribute.getDisplayName(), i, new Point(datetimetxtboxes[datecnt].Width, labels[i].Top - 3))); 
                datecnt++;
                break;
            case DocAttribute.LIST:
                combobox.Add(CreateComboBox(attribute.getDisplayName(), i, new Point(labels[i].Widt, 56 + (i * 30))));
                valLabel.Add(CreateValidationLabel(attribute.getDisplayName(), i, new Point(combobox[listcnt].Width, labels[i].Top - 3))); 
                listcnt++;
                break;
        }

    }

    if (txtboxes.Any()) panelMetaData.Controls.AddRange(txtboxes.ToArray());
    if (datetimetxtboxes.Any()) panelMetaData.Controls.AddRange(datetimetxtboxes.ToArray());
    if (combobox.Any()) panelMetaData.Controls.AddRange(combobox.ToArray());
    if (valLabel.Any()) panelMetaData.Controls.AddRange(valLabel.ToArray());
}
private TextBox CreateTextBox(string text, int value, Point location)
{
    TextBox textbox = new TextBox();
    textbox.Name =//somelogic
    textbox.Location = new Point(location.X, location.Y);
    textbox.Size = new Size(300, 21);

    return textbox;
}


private DateTimePicker CreateDateTimePicker(string text, int value, Point location)
{
    DateTimePicker datetextbox = new DateTimePicker();
    datetextbox.Name = //somelogic
    datetextbox.Location = new Point(location.X, location.Y);
    datetextbox.Size = new Size(300, 21);

    return datetextbox;
}


private ComboBox CreateComboBox(string text, int value, Point location)
{
    ComboBox combobox = new ComboBox();
    combobox.Name = //somelogic;
    combobox.Location = new Point(location.X, location.Y);
    combobox.Size = new Size(300, 21);

    return combobox;
}


private Label CreateLabel(string text, int value, Point location)
{
    Label label = new Label();
    label.Name =//somelogic;
    label.Location = new Point(location.X, location.Y);
    label.AutoSize = true;

    return label;
}


private Label CreateValidationLabel(string text, int value, Point location)
{
    Label label = new Label();
    label.Name = "vlb" + (text.Contains(".") ? text.Substring(0, text.IndexOf(".")) : text);
    label.Text = "*";
    label.Tag = value;
    label.Location = new Point(location.X, location.Y);
    label.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
    label.ForeColor = System.Drawing.Color.Red;
    label.AutoSize = true;

    return label;
}