C# 中窗体的 Control 属性中的控件顺序

问题描述 投票:0回答:6

我对将 FlowLayoutPanel 添加到表单的 controls 属性的顺序有一个特殊的问题。这是我尝试过的,

我在 C# 窗口应用程序中从左到右以垂直条状添加了 7 个 FlowLayoutPanel。然后我再次从左到右将流程布局标记为 1、2、3、... 7。现在在表单的加载处理程序中,我编写了以下代码片段,

    foreach (FlowLayoutPanel aDaysControl in this.Controls)
    {
        MessageBox.Show(aDaysControl.Tag.ToString());
    }

我预计消息会按照 1, 2, ... 7 的顺序出现。但我以相反的顺序得到了它(7, 6, ...1)。有人可以帮我解决我犯的错误吗??

保留订单的原因,

我正在尝试制作一个日历控件 每行代表一天。如果一个 这个月从星期三开始,然后我 需要添加一个空标签 第一个(周一)和第二个(周二) 排。所以顺序有点重要

c# winforms user-interface controls
6个回答
11
投票

我知道这是一个很老的问题,但是......

您可能想使用

SetChildIndex
。例如
this.Controls.SetChildIndex(button1, 0);


4
投票

查看它们添加到 yourForm.designer.cs 中表单的顺序


1
投票

如果您查看设计器 Form1.designer.cs 生成的代码,它将如下所示:

        // 
        // Form1
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(658, 160);
        this.Controls.Add(this.flowLayoutPanel7);
        this.Controls.Add(this.flowLayoutPanel6);
        this.Controls.Add(this.flowLayoutPanel5);
        this.Controls.Add(this.flowLayoutPanel4);
        this.Controls.Add(this.flowLayoutPanel3);
        this.Controls.Add(this.flowLayoutPanel2);
        this.Controls.Add(this.flowLayoutPanel1);
        this.Name = "Form1";
        this.Text = "Form1";
        this.ResumeLayout(false);

注意它是如何构建的,您先添加面板 1,然后添加面板 2,依此类推。 但当代码运行时,它会先添加 7,然后添加 6。

此代码将位于设计器生成的InitializeComponent()函数中。

为什么需要它们按一定的顺序运行?

我不会依赖设计师来保持你想要的顺序..我会自己对控件进行排序:

        var flowpanelinOrder = from n in this.Controls.Cast<Control>()
                               where n is FlowLayoutPanel
                               orderby int.Parse(n.Tag.ToString())
                               select n;

        /* non linq
        List<Control> flowpanelinOrder = new List<Control>();
        foreach (Control c in this.Controls)
        {
            if (c is FlowLayoutPanel) flowpanelinOrder.Add(c);                
        }
        flowpanelinOrder.Sort();
         * */

        foreach (FlowLayoutPanel aDaysControl in flowpanelinOrder)
        {
            MessageBox.Show(aDaysControl.Tag.ToString());
        }

1
投票

如果将来其他设计师删除控件、重新添加控件等怎么办?检查设计师总是一团糟。更好的方法是在枚举之前对容器控件中的控件进行排序。我使用这个扩展方法(如果你有 Linq):

public static List<Control> ToControlsSorted(this Control panel)
{
    var controls = panel.Controls.OfType<Control>().ToList();
    controls.Sort((c1, c2) => c1.TabIndex.CompareTo(c2.TabIndex));
    return controls;
}

你可以:

foreach (FlowLayoutPanel aDaysControl in this.ToControlsSorted())
{
    MessageBox.Show(aDaysControl.TabIndex.ToString());
}

(以上是

TabIndex
)。根据
Tag
进行排序是很简单的。


0
投票

真的有问题吗?

只要 UI 运行正确(例如,就 Tab 键顺序而言),我建议您不要对它们的枚举顺序做出任何假设。

编辑:感谢您更详细地解释您的要求。我想我仍然建议不要使用它们在 Controls 集合中存储的顺序。最好始终将这些实现细节视为“不透明”。您有一个与每个控件关联的标签,因此您可以使用它来识别正确的控件。为了加快处理速度,您可以构建一个按序数引用控件的 7 元素数组:

FlowLayoutPanel[] panels = new FlowLayoutPanel[7];

foreach(FlowLayoutPanel panel in this.Controls)
{
    panels[(int)panel.Tag] = panel;
}

// Now, you can reference the panels directly by subscript:

panels[2].BackColor = Color.Aquamarine;

尽管我会进行一些类型检查以使此代码更加健壮!


0
投票

我使用此方法设置 TabIndex 以反映视觉流 - 即控件的位置。

private void ChangeTabIndexByPosition(ControlCollectioncontrolsCollection) { 列表排序=controlsCollection.OfType().ToList(); Sorted.Sort((c1, c2) => c1.Top == c2.Top ? c1.Left.CompareTo(c2.Left) : c1.Top.CompareTo(c2.Top));

for (int i = 0; i < sorted.Count; i++)
{
    sorted[i].TabIndex = i;
}

}

© www.soinside.com 2019 - 2024. All rights reserved.