web-dev-qa-db-fra.com

VB.NET - Itération de contrôles dans un objet conteneur

J'ai un formulaire avec un bouton "Effacer".

Lorsque l'utilisateur clique sur "Effacer", je souhaite effacer la valeur de tous les éléments visibles du formulaire. Dans le cas des contrôles de date, je souhaite les réinitialiser à la date du jour.

Tous mes contrôles sont contenus dans un panneau.

En ce moment, je le fais avec le code ci-dessous. Existe-t-il un moyen plus simple que de vérifier manuellement chaque type de contrôle? Cette méthode semble excessivement lourde.

Pour aggraver les choses, afin de supprimer récursivement les contrôles à l'intérieur de sous-conteneurs (c'est-à-dire une zone de groupe dans le panneau), je dois répéter le monstre entier avec une version surchargée "GroupBox".

Edit: Grâce à vos suggestions, le code ci-dessous est grandement simplifié.

Private Sub btnClear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClear.Click
    'User clicks Clear, so clear all the controls within this panel
    ClearAllControls(panMid, True) 'True indicates that yes, i want to recurse through sub-containers
End Sub

ClearAllControls(ByRef container As Panel, Optional Recurse As Boolean = True)   
  'Clear all of the controls within the container object
  'If "Recurse" is true, then also clear controls within any sub-containers
  Dim ctrl As Control
  For Each ctrl In container.Controls
      If (ctrl.GetType() Is GetType(TextBox)) Then
          Dim txt As TextBox = CType(ctrl, TextBox)
          txt.Text = ""
      End If
      If (ctrl.GetType() Is GetType(CheckBox)) Then
          Dim chkbx As CheckBox = CType(ctrl, CheckBox)
          chkbx.Checked = False
      End If
      If (ctrl.GetType() Is GetType(ComboBox)) Then
          Dim cbobx As ComboBox = CType(ctrl, ComboBox)
          cbobx.SelectedIndex = -1
      End If
      If (ctrl.GetType() Is GetType(DateTimePicker)) Then
          Dim dtp As DateTimePicker = CType(ctrl, DateTimePicker)
          dtp.Value = Now()
      End If

      If Recurse Then
          If (ctrl.GetType() Is GetType(Panel)) Then
              Dim pnl As Panel = CType(ctrl, Panel)
              ClearAllControls(pnl, Recurse)
          End If
          If ctrl.GetType() Is GetType(GroupBox) Then
              Dim grbx As GroupBox = CType(ctrl, GroupBox)
              ClearAllControls(grbx, Recurse)
          End If
      End If
  Next
End Sub

@Theraccoonbear: J'aime votre suggestion, mais lorsque je change la déclaration en ceci:

Private Sub ClearAllControls(ByRef controls As ControlCollection, Optional ByVal Recurse As Boolean = True)

Ensuite, cette ligne me donne "Impossible de convertir l'objet de type 'ControlCollection' en 'ControlCollection'.":

  ClearAllControls(panMid.Controls)
21
JosephStyons

Vous pouvez ignorer les danses GetType et CType avec TryCast :

Dim dtp as DateTimePicker = TryCast(ctrl, DateTimePicker)
If dtp IsNot Nothing then dtp.Value = Now()

Cela vous fera économiser environ 10 lignes.

Une méthode extension off de la classe Control devrait la garder bien rangée:

<Extension()> _
Public Shared Sub ClearValue(c as Control, recursive as Boolean)
   Dim dtp as DateTimePicker = TryCast(c, DateTimePicker)
   If dtp IsNot Nothing Then dtp.Value = Now()
   ' Blah, Blah, Blah
End Sub

Edit: Si la pensée des méthodes d’extension Evil qui ignorent les exceptions NullReferenceException ne vous fait pas reculer

<Extension()> _
Public Shared Sub ClearValue(c as CheckBox)
   If c IsNot Nothing Then c.Checked = False
End Sub

TryCast(ctrl, CheckBox).ClearValue()
16
Mark Brackett

voici le code pour obtenir tout le contrôle de tous les contrôles de groupe d'un formulaire .__ et vous pouvez faire quelque chose dans le contrôle GroupBox

Private Sub GetControls()
    For Each GroupBoxCntrol As Control In Me.Controls
        If TypeOf GroupBoxCntrol Is GroupBox Then
            For Each cntrl As Control In GroupBoxCntrol.Controls
                'do somethin here

            Next
        End If

    Next
End Sub
8
Imran

Pourquoi ne pas juste avoir une routine

ClearAllControls(ByRef container As Control, Optional ByVal Recurse As Boolean = True)

Vous pouvez y accéder de nouveau, quel que soit le niveau de la hiérarchie où vous commencez l'appel, du niveau de formulaire à un seul conteneur.

En outre, sur les contrôles TextBox, j'utilise Textbox.Text = String.Empty

2
rjrapson
Public Sub raz(lst As Control.ControlCollection, Optional recursive As Boolean = True)
    For Each ctrl As Control In lst
        If TypeOf ctrl Is TextBox Then
            CType(ctrl, TextBox).Clear()
        End If

        If TypeOf ctrl Is MaskedTextBox Then
            CType(ctrl, MaskedTextBox).Clear()
        End If

        If TypeOf ctrl Is ComboBox Then
            CType(ctrl, ComboBox).SelectedIndex = -1
        End If

        If TypeOf ctrl Is DateTimePicker Then
            Dim dtp As DateTimePicker = CType(ctrl, DateTimePicker)
            dtp.CustomFormat = " "
        End If

        If TypeOf ctrl Is CheckedListBox Then
            Dim clbox As CheckedListBox = CType(ctrl, CheckedListBox)
            For i As Integer = 0 To clbox.Items.Count - 1
                clbox.SetItemChecked(i, False)
            Next
        End If

        If TypeOf ctrl Is RadioButton Then
            CType(ctrl, RadioButton).Checked = False

        End If

        If recursive Then
            If TypeOf ctrl Is GroupBox Then
                raz(CType(ctrl, GroupBox).Controls)
            End If
        End If
    Next
End Sub
1
user3692282

J'ai fait quelque chose de similaire et c'est fondamentalement la façon dont j'ai choisi de le faire. Le seul changement que je pourrais suggérer serait au lieu de surcharger la méthode, faites simplement du type passé en contrôle un contrôle et vous pouvez utiliser la même version pour GroupBox, Panel ou tout autre contrôle de conteneur fournissant une propriété .Controls. Autre que cela, je pense que la définition de "effacer" un contrôle peut être quelque peu ambiguë et donc il n'y a pas de méthode Clear () appartenant à la classe Control, vous devez donc implémenter ce que cela signifie pour vos besoins pour chaque type de contrôle.

1
theraccoonbear

Ici, cela fonctionne pour tous les contrôles internes.
Ajoutez si vous avez besoin d’autres contrôles.

Private Sub ClearAll()
    Try
        For Each ctrl As Control In Me.Controls
            If ctrl.[GetType]().Name = "Panel" Then
                ClearControls(ctrl)
            End If

            If ctrl.[GetType]().Name = "GroupBox" Then
                ClearControls(ctrl)
            End If
            If ctrl.[GetType]().Name = "ComboBox" Then
                Dim tb As ComboBox = TryCast(ctrl, ComboBox)
                tb.SelectedText = ""
            End If


            If ctrl.[GetType]().Name = "TabControl" Then
                ClearControls(ctrl)
            End If

            If ctrl.[GetType]().Name = "TextBox" Then
                Dim tb As TextBox = TryCast(ctrl, TextBox)
                tb.Clear()
            End If

            If ctrl.[GetType]().Name = "RadioButton" Then
                Dim tb As RadioButton = TryCast(ctrl, RadioButton)
                tb.Checked = False
            End If

            If ctrl.[GetType]().Name = "CheckBox" Then
                Dim tb As CheckBox = TryCast(ctrl, CheckBox)
                tb.Checked = False
            End If

            If ctrl.[GetType]().Name = "ComboBox" Then
                Dim tb As ComboBox = TryCast(ctrl, ComboBox)
                tb.SelectedIndex = 0
            End If

            If ctrl.[GetType]().Name = "RichTextBox" Then
                Dim tb As RichTextBox = TryCast(ctrl, RichTextBox)
                tb.Clear()

            End If
        Next
    Catch ex As Exception
        MessageBox.Show(ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try
End Sub


Private Sub ClearControls(ByVal Type As Control)

    Try
        For Each ctrl As Control In Type.Controls

            If ctrl.[GetType]().Name = "TextBox" Then
                Dim tb As TextBox = TryCast(ctrl, TextBox)
                tb.Clear()
            End If

            If ctrl.[GetType]().Name = "Panel" Then
                ClearControls(ctrl)
            End If

            If ctrl.[GetType]().Name = "GroupBox" Then
                ClearControls(ctrl)
            End If

            If ctrl.[GetType]().Name = "TabPage" Then
                ClearControls(ctrl)
            End If

            If ctrl.[GetType]().Name = "ComboBox" Then
                Dim tb As ComboBox = TryCast(ctrl, ComboBox)
                tb.SelectedText = ""
            End If

            If ctrl.[GetType]().Name = "RadioButton" Then
                Dim tb As RadioButton = TryCast(ctrl, RadioButton)
                tb.Checked = False
            End If

            If ctrl.[GetType]().Name = "CheckBox" Then
                Dim tb As CheckBox = TryCast(ctrl, CheckBox)
                tb.Checked = False
            End If

            If ctrl.[GetType]().Name = "RichTextBox" Then
                Dim tb As RichTextBox = TryCast(ctrl, RichTextBox)
                tb.Clear()

            End If
        Next
    Catch ex As Exception
        MessageBox.Show(ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try
End Sub
1
Sekhar Babu
For Each c In CONTAINER.Controls
    If TypeOf c Is TextBox Then
        c.Text = ""
    End If
Next

Remplacez le (CONTENEUR) par votre nom (il peut s'agir d'un FORMULAIRE, d'un PANNEAU, d'un GROUPBOX)
Faites attention à ce que vous avez inclus vos contrôles dans.

1
ShoushouLebanon

Cela vient directement d'un article discutant des techniques à utiliser maintenant que Control Arrays a été supprimé du passage de VB6 à VB.NET.

Private Sub ClearForm(ByVal ctrlParent As Control)
    Dim ctrl As Control
    For Each ctrl In ctrlParent.Controls
        If TypeOf ctrl Is TextBox Then
           ctrl.Text = ""
        End If
        ' If the control has children, 
        ' recursively call this function
        If ctrl.HasChildren Then
            ClearForm(ctrl)
        End If
    Next
End Sub
1
dmcgill50

Je vous présente ma classe ControlIterator

Source: http://Pastebin.com/dubt4nPG

Quelques exemples d'utilisation:

 ControlIterator.Disable(CheckBox1)

 ControlIterator.Enable({CheckBox1, CheckBox2})

 ControlIterator.Check(Of CheckBox)(Me)

 ControlIterator.Uncheck(Of CheckBox)(Me.GroupBox1)

 ControlIterator.Hide(Of CheckBox)("1")

 ControlIterator.PerformAction(Of CheckBox)(Sub(ctrl As CheckBox) ctrl.Visible = True)

 ControlIterator.AsyncPerformAction(RichTextBox1,
                                    Sub(rb As RichTextBox)
                                        For n As Integer = 0 To 9
                                            rb.AppendText(CStr(n))
                                        Next
                                    End Sub)

 ControlIterator.PerformAction(Me.Controls, Sub(c As Control)
                                                c.BackColor = Color.Green
                                            End Sub)
0
ElektroStudios