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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/280497/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 21:24:38  来源:igfitidea点击:

Order of controls in a form's Control property in C#

c#winformsuser-interfacecontrols

提问by

I am having a peculiar problem with the order in which FlowLayoutPanels are added in to the form's controlsproperty. This is what I tried,

我对 FlowLayoutPanels 添加到表单控件属性的顺序有一个特殊的问题。这是我试过的,

I added 7 FlowLayoutPanels in to a C# window application from left to right in vertical strips. Then I tagged the flow layouts as 1, 2, 3, ... 7 again from left to right. Now in the load handler of the form, I wrote the following snippet,

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

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

I expected messages to appear in the order of 1, 2, ... 7. But I got it in the reverse order (7, 6, ...1). Could some one help me out with the mistake I did ??

我希望消息按1, 2, ... 7的顺序出现。但我以相反的顺序得到它(7、6、...1)。有人能帮我解决我犯的错误吗??

Reason behind preserving the order,

保留订单背后的原因,

I am trying to make a calendar control with each row representing a day. If a month starts from Wednesday, then I need to add a empty label to the first(Monday) and the second(Tuesday) row. So the order matters a bit

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

采纳答案by Mladen Prajdic

look at the order in which they are added to the form in the yourForm.designer.cs

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

回答by Steve Morgan

Is it really a problem?

真的有问题吗?

As long as the UI operates correctly (in terms of tab order, for example), I'd recommend that you don't make any assumptions about the order in which they're enumerated.

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

EDIT: Thanks for explaining your requirement in more detail. I think I'd still recommend against using the order that they're stored in the Controls collection. It's always best to consider these implementation details to be 'opaque'. You have a tag associated with each control, so you can use this to identify the correct control. In order to speed up the processing, you could build a 7-element array that references the controls by ordinal:

编辑:感谢您更详细地解释您的要求。我想我仍然建议不要使用它们存储在 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;

Though I'd put some type-checking in to make this code a bit more robust!

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

回答by Hath

if you look at the code generated by the designer Form1.designer.cs it will look something like this:

如果您查看由设计器 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);

note how it was built up you added panel 1 first then 2 etc. but as the code runs through it will add 7 first then 6.

请注意它是如何构建的,您首先添加了面板 1,然后添加了 2 等,但随着代码运行,它将先添加 7,然后添加 6。

this code will be in the InitializeComponent() function generated by the designer.

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

Why do you need them to run in a certain order?

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

I wouldn't rely on the designer to keep the order you want.. i would sort the controls my self:

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

        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());
        }

回答by ispiro

I know this is quite an old question, but...

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

You might want to use SetChildIndex. e.g. this.Controls.SetChildIndex(button1, 0);

您可能想要使用SetChildIndex. 例如this.Controls.SetChildIndex(button1, 0);

回答by nawfal

What if in future some other designer removed the controls, added back etc? Checking the designer always is a mess. What would be better is to sort the controls in the container control before you enumerate. I use this extension method (if you have Linq):

如果将来其他一些设计师删除控件,添加回来等怎么办?检查设计师总是一团糟。最好是在枚举之前对容器控件中的控件进行排序。我使用这个扩展方法(如果你有 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;
}

And you can:

你可以:

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

(Above is for TabIndex). Would be trivial to sort according to Tagfrom that.

(以上为TabIndex)。从中排序会很简单Tag