When using the GetAll
method in the top answer here to recursively get all ComboBoxes on a Form, the results behave strangely if the ComboBoxes are in an UltraGroupBox. I get inconsistent results when manipulating the returned IEnumerable with LINQ vs. foreach. See the standalone program example further down to reproduce the problem for yourself. The problem is exemplified in the following code snippet:
var combos = GetAll(this, typeof(ComboBox)).Cast<ComboBox>();
var linqNames = combos.Select(c => c.Name).ToList();
var foreachNames = new List<string>();
foreach (var comboBox in combos)
{
foreachNames.Add(comboBox.Name);
}
Debug.WriteLine(String.Join(", ", linqNames));
Debug.WriteLine(String.Join(", ", foreachNames));
Output:
cbo1, cbo2, cbo3, cbo4, cbo5, cbo6, cbo7
cbo1, cbo3, cbo5, cbo1, cbo5, cbo5, cbo7
Notice that cbo2, cbo4, and cbo6 are missing from the foreach result. This is executing in the Form's load event handler. The ComboBoxes are all within the same Infragistics UltraGroupBox. What causes this odd behavior? Does the Controls property of an UltraGroupBox have side effects?
Edit: I realize that adding ToList() to the return of GetAll (as below) causes the results to match, but I want to know why the enumeration is inconsistent when just using the IEnumerable.
var combos = GetAll(this, typeof(ComboBox)).Cast<ComboBox>().ToList();
Edit 2: Here is the Designer code for the standalone program (using .NET 4.0 and Infragistics NetAdvantage 2013.1 assemblies):
namespace WindowsFormsApplication2
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
Infragistics.Win.Appearance appearance1 = new Infragistics.Win.Appearance();
this.grpTest = new Infragistics.Win.Misc.UltraGroupBox();
this.label20 = new System.Windows.Forms.Label();
this.label18 = new System.Windows.Forms.Label();
this.label14 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.cbo4 = new System.Windows.Forms.ComboBox();
this.cbo6 = new System.Windows.Forms.ComboBox();
this.cbo5 = new System.Windows.Forms.ComboBox();
this.cbo2 = new System.Windows.Forms.ComboBox();
this.cbo3 = new System.Windows.Forms.ComboBox();
this.cbo1 = new System.Windows.Forms.ComboBox();
((System.ComponentModel.ISupportInitialize)(this.grpTest)).BeginInit();
this.grpTest.SuspendLayout();
this.SuspendLayout();
//
// grpTest
//
this.grpTest.BorderStyle = Infragistics.Win.Misc.GroupBoxBorderStyle.None;
this.grpTest.Controls.Add(this.label20);
this.grpTest.Controls.Add(this.label18);
this.grpTest.Controls.Add(this.label14);
this.grpTest.Controls.Add(this.label5);
this.grpTest.Controls.Add(this.label4);
this.grpTest.Controls.Add(this.label3);
this.grpTest.Controls.Add(this.cbo4);
this.grpTest.Controls.Add(this.cbo6);
this.grpTest.Controls.Add(this.cbo5);
this.grpTest.Controls.Add(this.cbo2);
this.grpTest.Controls.Add(this.cbo3);
this.grpTest.Controls.Add(this.cbo1);
this.grpTest.Dock = System.Windows.Forms.DockStyle.Top;
appearance1.BackColor = System.Drawing.Color.DimGray;
appearance1.BackColor2 = System.Drawing.Color.DimGray;
appearance1.FontData.BoldAsString = "True";
appearance1.FontData.SizeInPoints = 10F;
appearance1.ForeColor = System.Drawing.Color.White;
this.grpTest.HeaderAppearance = appearance1;
this.grpTest.Location = new System.Drawing.Point(0, 0);
this.grpTest.Name = "grpTest";
this.grpTest.Size = new System.Drawing.Size(463, 261);
this.grpTest.TabIndex = 13;
this.grpTest.Text = "Test";
//
// label20
//
this.label20.AutoSize = true;
this.label20.Location = new System.Drawing.Point(135, 180);
this.label20.Name = "label20";
this.label20.Size = new System.Drawing.Size(49, 13);
this.label20.TabIndex = 25;
this.label20.Text = "Combo 6";
//
// label18
//
this.label18.AutoSize = true;
this.label18.Location = new System.Drawing.Point(134, 158);
this.label18.Name = "label18";
this.label18.Size = new System.Drawing.Size(49, 13);
this.label18.TabIndex = 24;
this.label18.Text = "Combo 5";
//
// label14
//
this.label14.AutoSize = true;
this.label14.Location = new System.Drawing.Point(133, 136);
this.label14.Name = "label14";
this.label14.Size = new System.Drawing.Size(49, 13);
this.label14.TabIndex = 23;
this.label14.Text = "Combo 4";
//
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(134, 114);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(49, 13);
this.label5.TabIndex = 22;
this.label5.Text = "Combo 3";
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(134, 92);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(49, 13);
this.label4.TabIndex = 21;
this.label4.Text = "Combo 2";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(134, 70);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(49, 13);
this.label3.TabIndex = 20;
this.label3.Text = "Combo 1";
//
// cbo4
//
this.cbo4.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
this.cbo4.FormattingEnabled = true;
this.cbo4.Items.AddRange(new object[] {
"A",
"B"});
this.cbo4.Location = new System.Drawing.Point(190, 133);
this.cbo4.Name = "cbo4";
this.cbo4.Size = new System.Drawing.Size(121, 21);
this.cbo4.TabIndex = 7;
//
// cbo6
//
this.cbo6.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
this.cbo6.FormattingEnabled = true;
this.cbo6.Items.AddRange(new object[] {
"A",
"B"});
this.cbo6.Location = new System.Drawing.Point(190, 177);
this.cbo6.Name = "cbo6";
this.cbo6.Size = new System.Drawing.Size(121, 21);
this.cbo6.TabIndex = 11;
//
// cbo5
//
this.cbo5.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
this.cbo5.FormattingEnabled = true;
this.cbo5.Items.AddRange(new object[] {
"A",
"B",
"C"});
this.cbo5.Location = new System.Drawing.Point(190, 155);
this.cbo5.Name = "cbo5";
this.cbo5.Size = new System.Drawing.Size(121, 21);
this.cbo5.TabIndex = 9;
//
// cbo2
//
this.cbo2.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
this.cbo2.FormattingEnabled = true;
this.cbo2.Items.AddRange(new object[] {
"A",
"B",
"C"});
this.cbo2.Location = new System.Drawing.Point(190, 89);
this.cbo2.Name = "cbo2";
this.cbo2.Size = new System.Drawing.Size(121, 21);
this.cbo2.TabIndex = 4;
//
// cbo3
//
this.cbo3.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
this.cbo3.FormattingEnabled = true;
this.cbo3.Items.AddRange(new object[] {
"A",
"B"});
this.cbo3.Location = new System.Drawing.Point(190, 111);
this.cbo3.Name = "cbo3";
this.cbo3.Size = new System.Drawing.Size(121, 21);
this.cbo3.TabIndex = 5;
//
// cbo1
//
this.cbo1.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
this.cbo1.FormattingEnabled = true;
this.cbo1.Items.AddRange(new object[] {
"A",
"B",
"C"});
this.cbo1.Location = new System.Drawing.Point(190, 67);
this.cbo1.Name = "cbo1";
this.cbo1.Size = new System.Drawing.Size(121, 21);
this.cbo1.TabIndex = 3;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(463, 277);
this.Controls.Add(this.grpTest);
this.Name = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
((System.ComponentModel.ISupportInitialize)(this.grpTest)).EndInit();
this.grpTest.ResumeLayout(false);
this.grpTest.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private Infragistics.Win.Misc.UltraGroupBox grpTest;
private System.Windows.Forms.ComboBox cbo3;
private System.Windows.Forms.ComboBox cbo2;
private System.Windows.Forms.ComboBox cbo1;
private System.Windows.Forms.Label label20;
private System.Windows.Forms.Label label18;
private System.Windows.Forms.Label label14;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.ComboBox cbo6;
private System.Windows.Forms.ComboBox cbo5;
private System.Windows.Forms.ComboBox cbo4;
}
}
And the main implementation file:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
if (!DesignMode)
{
var combos = GetAll(this, typeof(ComboBox)).Cast<ComboBox>();
var names = combos.Select(c => c.Name).ToList();
var foreachNames = new List<string>();
foreach (var comboBox in combos)
{
foreachNames.Add(comboBox.Name);
}
Debug.WriteLine(String.Join(", ", names));
Debug.WriteLine(String.Join(", ", foreachNames));
}
}
private IEnumerable<Control> GetAll(Control control, Type type)
{
IEnumerable<Control> controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetAll(ctrl, type))
.Concat(controls)
.Where(c => c.GetType() == type);
}
}
}