将标签和文本框定位在每行3个组中的算法

时间:2012-09-28 14:53:46

标签: c# winforms controls alignment

根据XML文件内容,在运行时,程序必须动态创建文本框和标签。我想在组框内组织以下控件:

[label1] [textbox1]  [label2] [texbox2] [label3] [textbox]
[label4] [textbox4]  [label5] [textbox5] [...]

等等。

但我不知道如何计算XY值。我尝试了几种解决方案,但没有运气。在我目前的实现下面,每行放置标签和文本框:

[label1] [texbox1]
[labe2] [texbox2] 

等等。

       //list the disiciplanas from XML file
            //into combobox control.
            for (int i = 0,
                label_X = 20, label_Y = 20,
                textbox_X = 74, textbox_Y = 20,
                len = materias[0].ChildNodes.Count,
                line = 0, tmp_pos = 20;

                i < len;

                i++,
                tab_index++,
                line++,
                tmp_pos += 20
                )
            {
                XmlNode materia = materias[0].ChildNodes[i];
                Point label_position, textbox_position;
                Label label = new Label();
                TextBox textbox = new TextBox();

#if DEBUG_
                if (line == 3)
                {
                    label_X = 200 + tmp_pos;
                    label_Y = 25 + tmp_pos;
                }
                else
                {
                    label_X += 10;
                }

                textbox_Y = label_Y;

#else
                label_Y += 20;
                textbox_Y = label_Y;
#endif

                label.Text = "foo";

                textbox.Size = new Size(48, 20);
                textbox.Name = String.Format("nota{0}", fo.Name);

                label_position = new Point();
                label_position.X = label_X;
                label_position.Y = label_Y;

                textbox_position = new Point();
                textbox_position.X = textbox_X;
                textbox_position.Y = textbox_Y;

                label.Location = label_position;
                textbox.Location = textbox_position;
                textbox.Left = 150;
                textbox.TabIndex = tab_index;

                notas_panel.Controls.Add(label);
                notas_panel.Controls.Add(textbox);
            }

我希望这很清楚。提前致谢

2 个答案:

答案 0 :(得分:2)

最简单的方法是不计算它们。

创建一个面板并摆脱它的边框。在面板上创建动态控件并将面板设置为Dock Top,然后调用BringToFront()(或者可能是SendToBack()我永远无法记住它们在运行时的哪个方向可以帮助对接。)小组。

当您创建下一个批次时,控件都具有相同的位置,但它们的父面板会自动放在前一个下面。

结果应如下所示: enter image description here

 public partial class Form1 : Form
{
    List<Int32> Children;
    public Form1()
    {
        InitializeComponent();
        Children = new List<int>();
        Children.AddRange(Enumerable.Range(0, 20));
        ShowChildren();
    }

    private void ShowChildren()
    {
        for (int i = 0; i < Children.Count; i += 3)
        {
            AddRow(i, Children);
        }
    }

    private void AddRow(int startIndex, List<Int32> Nodes)
    {
        int NodesOnThisRow = 3;
        if (Nodes.Count - startIndex < 3)
            NodesOnThisRow = Nodes.Count - startIndex;
        Panel newPanel = new Panel();
        newPanel.Height = 25;
        int x = 8;
        for (int i = 0; i < NodesOnThisRow; i++)
        {
            Label L = new Label();
            TextBox T = new TextBox();
            //You could dock these left so they just appear one after the other, or since there
            //is only 3 you could just hard code the 3 x values, or calc them
            L.Left = x;
            T.Left = x + 120;
            L.Text = Nodes[startIndex + i].ToString();
            T.Text = Nodes[startIndex + i].ToString();
            x += 250;
            newPanel.Controls.Add(L);
            newPanel.Controls.Add(T);
        }
        groupBox1.Controls.Add(newPanel);
        newPanel.Dock = DockStyle.Top;
        newPanel.BringToFront();
    }
}

答案 1 :(得分:2)

public IEnumerable<Point> GetLocations(int numCols,int colWidth,int rowHeight)
{
    int x = 0, y = 0;
    while (true)
    {
        for (int i = 0; i < numCols; i++)
        {
            yield return new Point(x, y);
            x += colWidth;
        }
        x = 0;
        y += rowHeight;
    }
}

您可以像

一样使用它
foreach (Point p in GetLocations(3, 100, 32).Take(12))
{
    Console.WriteLine(p);
}