简体   繁体   English

C#中表单的Control属性中的控件顺序

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

I am having a peculiar problem with the order in which FlowLayoutPanels are added in to the form's controls property. 我对FlowLayoutPanels添加到表单的controls属性的顺序有一个特殊的问题。 This is what I tried, 这是我试过的,

I added 7 FlowLayoutPanels in to a C# window application from left to right in vertical strips. 我在垂直条带中从左到右添加了7个FlowLayoutPanel到C#窗口应用程序。 Then I tagged the flow layouts as 1, 2, 3, ... 7 again from left to right. 然后我再次从左到右标记流布局为1,2,3,... 7。 Now in the load handler of the form, I wrote the following snippet, 现在在表单的加载处理程序中,我编写了以下代码段,

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

I expected messages to appear in the order of 1, 2, ... 7 . 我希望消息以1,2,... 7的顺序出现。 But I got it in the reverse order (7, 6, ...1). 但我按相反的顺序得到它(7,6,...... 1)。 Could some one help me out with the mistake I did ?? 有人可以帮助我解决我做的错误吗?

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 所以顺序有点重要

I know this is quite an old question, but... 我知道这是一个很老的问题,但......

You might want to use SetChildIndex . 您可能想要使用SetChildIndex eg this.Controls.SetChildIndex(button1, 0); 例如this.Controls.SetChildIndex(button1, 0);

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

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 ). (上面是TabIndex )。 Would be trivial to sort according to Tag from that. 根据Tag从那里排序是微不足道的。

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

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. 我想我仍然建议不要使用它们存储在Controls集合中的顺序。 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: 为了加快处理速度,您可以构建一个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! 虽然我会进行一些类型检查,以使这个代码更健壮!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM