web-dev-qa-db-fra.com

Obtenir tous les contrôles d'un type spécifique

J'ai plusieurs PictureBox et j'ai besoin d'y charger des images aléatoires pendant l'exécution. J'ai donc pensé qu'il serait bien d'avoir une collection de toutes les boîtes à images puis de leur attribuer des images à l'aide d'une simple boucle. Mais comment dois-je le faire? Ou peut-être existe-t-il d'autres solutions plus efficaces à ce problème?

35
drv

En utilisant un peu de LINQ:

foreach(var pb in this.Controls.OfType<PictureBox>())
{
  //do stuff
}

Cependant, cela ne prendra en charge que les PictureBox dans le conteneur principal.

69
Femaref

Vous pouvez utiliser cette méthode:

public static IEnumerable<T> GetControlsOfType<T>(Control root)
    where T : Control
{
    var t = root as T;
    if (t != null)
        yield return t;

    var container = root as ContainerControl;
    if (container != null)
        foreach (Control c in container.Controls)
            foreach (var i in GetControlsOfType<T>(c))
                yield return i;
}

Ensuite, vous pourriez faire quelque chose comme ça:

foreach (var pictureBox in GetControlsOfType<PictureBox>(theForm)) {
    // ...
}
23
cdhowie

Si vous êtes au moins sur .NET 3.5, alors vous avez LINQ, ce qui signifie que depuis que ControlCollection implémente IEnumerable, vous pouvez simplement faire:

var pictureBoxes = Controls.OfType<PictureBox>();
7
Dan Tao

Une fonction simple, facile à comprendre, récursive et qui fonctionne en l'appelant dans n'importe quel contrôle de formulaire:

private void findControlsOfType(Type type, Control.ControlCollection formControls, ref List<Control> controls)
    {
        foreach (Control control in formControls)
        {
            if (control.GetType() == type)
                controls.Add(control);
            if (control.Controls.Count > 0)
                findControlsOfType(type, control.Controls, ref controls);
        }
    }

Vous pouvez l’appeler de différentes façons . Pour obtenir les boutons:

List<Control> buttons = new List<Control>();
findControlsOfType(typeof(Button), this.Controls, ref buttons);

Pour obtenir les panneaux:

List<Control> panels = new List<Control>();
findControlsOfType(typeof(Panel), this.Controls, ref panels);

etc.

2
Zelkovar
    public static List<T> FindControlByType<T>(Control mainControl,bool getAllChild = false) where T :Control
    {
        List<T> lt = new List<T>();
        for (int i = 0; i < mainControl.Controls.Count; i++)
        {
            if (mainControl.Controls[i] is T) lt.Add((T)mainControl.Controls[i]);
            if (getAllChild) lt.AddRange(FindControlByType<T>(mainControl.Controls[i], getAllChild));
        }
        return lt;
    }
2

Voici une autre version puisque les versions existantes ne correspondaient pas exactement à ce que j'avais en tête. Celui-ci fonctionne comme une méthode d'extension, en option, et exclut la vérification du type du conteneur racine/parent. Cette méthode est fondamentalement une méthode "Obtenir tous les contrôles descendants de type T":

public static System.Collections.Generic.IEnumerable<T> ControlsOfType<T>(this System.Web.UI.Control control) where T: System.Web.UI.Control{
    foreach(System.Web.UI.Control childControl in control.Controls){
        if(childControl is T) yield return (T)childControl;
        foreach(var furtherDescendantControl in childControl.ControlsOfType<T>()) yield return furtherDescendantControl;
    }
}
2
scradam

J'utilise cette méthode récursive générique:

L'hypothèse de cette méthode est que si le contrôle est T, la méthode ne regarde pas dans ses enfants. Si vous devez également regarder ses enfants, vous pouvez facilement le changer en conséquence.

public static IList<T> GetAllControlsRecusrvive<T>(Control control) where T :Control 
{
    var rtn = new List<T>();
    foreach (Control item in control.Controls)
    {
        var ctr = item as T;
        if (ctr!=null)
        {
            rtn.Add(ctr);
        }
        else
        {
            rtn.AddRange(GetAllControlsRecusrvive<T>(item));
        }

    }
    return rtn;
}
1
giammin

Prend le contrôle en tant que conteneur en compte:

        private static IEnumerable<T> GetControlsOfType<T>(this Control root)
        where T : Control
    {
        if (root is T t)
            yield return t;

        if (root is ContainerControl || root is Control)
        {
            var container = root as Control;
            foreach (Control c in container.Controls)
                foreach (var i in GetControlsOfType<T>(c))
                    yield return i;
        }
    }
0

Pour moi, c'est de loin le plus facile. Dans ma candidature, j'essayais de vider tous les champs de texte d'un panneau:

    foreach (Control c in panel.Controls)
    {
        if (c.GetType().Name == "TextBox")
        {
            c.Text = "";
        }
    }
0
Richard Martin