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

Accepted answer
Score: 11

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

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

Score: 4

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

Score: 1

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

        // 
        // 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 7 up you added panel 1 first then 2 etc. but 6 as the code runs through it will add 7 first 5 then 6.

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

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

I wouldn't 2 rely on the designer to keep the order you 1 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());
        }
Score: 1

What if in future some other designer removed 7 the controls, added back etc? Checking the 6 designer always is a mess. What would be 5 better is to sort the controls in the container 4 control before you enumerate. I use this 3 extension method (if you have 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 2 you can:

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

(Above is for TabIndex). Would be trivial 1 to sort according to Tag from that.

Score: 0

Is it really a problem?

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

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

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 1 in to make this code a bit more robust!

More Related questions