¿Cómo obtener TODOS los controles secundarios de un formulario de Windows Forms de un tipo específico (Botón/Cuadro de texto)?
Necesito obtener todos los controles en un formulario que sean del tipo x. Estoy bastante seguro de que vi ese código una vez en el pasado que usaba algo como esto:
dim ctrls() as Control
ctrls = Me.Controls(GetType(TextBox))
Sé que puedo iterar sobre todos los controles para que los niños utilicen una función recursiva, pero ¿hay algo más fácil o más directo, tal vez como lo siguiente?
Dim Ctrls = From ctrl In Me.Controls Where ctrl.GetType Is Textbox
Aquí tienes otra opción. Lo probé creando una aplicación de muestra, luego puse un GroupBox y un GroupBox dentro del GroupBox inicial. Dentro del GroupBox anidado puse 3 controles TextBox y un botón. Este es el código que utilicé (incluso incluye la recursividad que estabas buscando)
public IEnumerable<Control> GetAll(Control control,Type type)
{
var controls = control.Controls.Cast<Control>();
return controls.SelectMany(ctrl => GetAll(ctrl,type))
.Concat(controls)
.Where(c => c.GetType() == type);
}
Para probarlo en el evento de carga del formulario, quería un recuento de todos los controles dentro del GroupBox inicial.
private void Form1_Load(object sender, EventArgs e)
{
var c = GetAll(this,typeof(TextBox));
MessageBox.Show("Total Controls: " + c.Count());
}
Y devolvió el recuento correcto cada vez, así que creo que esto funcionará perfectamente para lo que estás buscando :)
En C# (ya que lo etiquetó como tal) podría usar una expresión LINQ como esta:
List<Control> c = Controls.OfType<TextBox>().Cast<Control>().ToList();
Editar para recursividad:
En este ejemplo, primero crea la lista de controles y luego llama a un método para completarla. Como el método es recursivo, no devuelve la lista, simplemente la actualiza.
List<Control> ControlList = new List<Control>();
private void GetAllControls(Control container)
{
foreach (Control c in container.Controls)
{
GetAllControls(c);
if (c is TextBox) ControlList.Add(c);
}
}
Es posible hacer esto en una declaración LINQ usando la Descendants
función, aunque no estoy tan familiarizado con ella. Consulte esta página para obtener más información al respecto.
Edite 2 para devolver una colección:
Como sugirió @ProfK, un método que simplemente devuelva los controles deseados probablemente sea una mejor práctica. Para ilustrar esto, he modificado el código de la siguiente manera:
private IEnumerable<Control> GetAllTextBoxControls(Control container)
{
List<Control> controlList = new List<Control>();
foreach (Control c in container.Controls)
{
controlList.AddRange(GetAllTextBoxControls(c));
if (c is TextBox)
controlList.Add(c);
}
return controlList;
}