web-dev-qa-db-fra.com

boucle sur toutes les zones de texte d'un formulaire, y compris celles à l'intérieur d'une zone de groupe

J'ai plusieurs zones de texte dans un winform, certaines d'entre elles sont dans une zone de groupe. J'ai essayé de parcourir toutes les zones de texte de ma fiche:

For Each c As Control In Me.Controls
    If c.GetType Is GetType(TextBox) Then
        ' Do something
    End If
Next

Mais il semblait ignorer ceux de la zone de groupe et passer en boucle par-dessus les autres zones de texte du formulaire. J'ai donc ajouté une autre boucle For Each pour les zones de texte de la zone de groupe:

For Each c As Control In GroupBox1.Controls
    If c.GetType Is GetType(TextBox) Then
        ' Do something
    End If
Next

Je me demande: existe-t-il un moyen de parcourir toutes les zones de texte d'un formulaire, y compris celles d'un groupe, avec une seule boucle For Each? Ou un moyen meilleur/plus élégant de le faire?

Merci d'avance.

12
kodkod

Vous pouvez utiliser cette fonction, linq pourrait être un moyen plus élégant.

Dim allTxt As New List(Of Control)
For Each txt As TextBox In FindControlRecursive(allTxt, Me, GetType(TextBox))
   '....'
Next

Public Shared Function FindControlRecursive(ByVal list As List(Of Control), ByVal parent As Control, ByVal ctrlType As System.Type) As List(Of Control)
    If parent Is Nothing Then Return list
    If parent.GetType Is ctrlType Then
        list.Add(parent)
    End If
    For Each child As Control In parent.Controls
        FindControlRecursive(list, child, ctrlType)
    Next
    Return list
End Function
18
Rango

Vous voudriez faire récursivité , par exemple (pseudocode, puisque je ne connais pas VB):

Sub LoopControls (Control Container)
    if (Container has Controls)
        LoopControls(Container)
    For Each c As Control In Container
        if (Control is TextBox)
            // do stuff
End Sub

Vous transmettriez votre formulaire (moi) au sous-marin initialement et celui-ci parcourra les contrôles qu'il contient en recherchant ceux qui contiennent plus de contrôles.

Consultez également cette question: VB.NET - Itération dans les contrôles d’un objet conteneur

1
JYelton

Si vous ne vous souciez pas de l'ordre (et je ne peux pas imaginer de raison pour laquelle vous devriez) des commandes, vous pouvez le faire de manière itérative de la manière suivante (c'est assez simple, donc je ne pense pas qu'aucune explication soit nécessaire) ). Devrait être beaucoup plus efficace que toute récursion, en particulier si vous avez plusieurs contrôles imbriqués, même si je doute que le gain de performances soit évident.

Public Function FindAllControlsIterative(ByRef parent As Control) As List(Of TextBox)
    Dim list As New List(Of TextBox)
    Dim ContainerStack As New Stack(Of Control)
    ContainerStack.Push(parent)
    While ContainerStack.Count > 0
        For Each child As Control In ContainerStack.Pop().Controls
            If child.HasChildren Then ContainerStack.Push(child)
            If child.GetType Is GetType(TextBox) Then list.Add(child)
        Next
    End While
    Return list
End Function
0
PulseJet

Vous devrez utiliser la récursivité. Ce qui suit est une solution C # utilisant une méthode d’extension et va un peu au-delà de votre question, mais je l’ai extraite de notre framework.

static partial class ControlExtensions
{
    public static void ApplyToMatchingChild(this Control parent, Action<Control> actionToApplyWhenFound, bool keepApplyingForever, params Func<Control, bool>[] matchingChildCriteria)
    {
        ControlEventHandler reapplyEventHandler = null;
        if (keepApplyingForever)
        {
            reapplyEventHandler = (s, e) =>
            {
                ApplyToMatchingChild(e.Control, actionToApplyWhenFound, keepApplyingForever, matchingChildCriteria);
            };
        }
        SearchForMatchingChildTypes(parent, actionToApplyWhenFound, reapplyEventHandler, matchingChildCriteria);
    }

    private static void SearchForMatchingChildTypes(Control control, Action<Control> actionToApplyWhenFound, ControlEventHandler reapplyEventHandler, params Func<Control, bool>[] matchingChildCriteria)
    {
        if (matchingChildCriteria.Any(criteria => criteria(control)))
        {
            actionToApplyWhenFound(control);
        }

        if (reapplyEventHandler != null)
        {
            control.ControlAdded += reapplyEventHandler;
        }

        if (control.HasChildren)
        {
            foreach (var ctl in control.Controls.Cast<Control>())
            {
                SearchForMatchingChildTypes(ctl, actionToApplyWhenFound, reapplyEventHandler, matchingChildCriteria);
            }
        }
    }
}

Et appeler:

myControl.ApplyToMatchingChild(c => { /* Do Stuff to c */ return; }, false, c => c is TextBox);

Cela va appliquer une fonction à tous les champs de texte enfants. Vous pouvez utiliser le paramètre keepApplyingForever pour vous assurer que votre fonction sera appliquée lors de l'ajout ultérieur de contrôles enfants. La fonction vous permettra également de spécifier un nombre quelconque de critères correspondants, par exemple, si le contrôle est également une étiquette ou un autre critère.

Nous l'utilisons en fait comme un moyen simple d'appeler notre conteneur d'injection de dépendance pour chaque contrôle UserControl ajouté à notre formulaire.

Je suis sûr que vous ne devriez pas avoir beaucoup de problèmes le convertir en VB.NET aussi ... De plus, si vous ne voulez pas de la fonctionnalité "keepApplyingForever", il devrait être assez facile de la supprimer aussi.

0
Reddog