2015-05-18 9 views
13

Nella mia applicazione ho una casella di gruppo che contiene controlli figlio. (Come visto nella foto dettagliata). Voglio enumerare tutte le caselle di testo per eseguire alcune convalide utilizzando un semplice ciclo foreach.Ottieni l'elenco di controlli secondari all'interno di una casella di gruppo

Questo schema documento darebbe una giusta idea della custodia dei controlli

enter image description here

foreach (Control control in grpBxTargetSensitivity.Controls) 
      { 
       if (control is FlowLayoutPanel && control.HasChildren) 
       { 
        foreach (Control ctrl in control.Controls) 
        { 
         if (ctrl is Panel && ctrl.HasChildren) 
         { 
          foreach (Control tbox in ctrl.Controls) 
          { 
           if (tbox is TextBox) 
           { 
            TextBox textbox = tbox as TextBox; 
            validData &= !string.IsNullOrWhiteSpace(textbox.Text); 
           } 
          } 
         } 
        } 
       } 
      } 

La mia domanda è: esiste un modo migliore (possibilmente attraverso LINQ) per ottenere tutti i controlli, tra cui le caselle di testo ospitate all'interno dei pannelli rispetto al metodo sopra.?

risposta

15

Non so che questo è meglio .. se è più facile da leggere è una questione di opinione:

var validData 
    = grpBxTargetSensitivity.Controls.OfType<FlowLayoutPanel>() 
          .SelectMany(c => c.Controls.OfType<Panel>()) 
          .SelectMany(c => c.Controls.OfType<TextBox>()) 
          .All(textbox => !string.IsNullOrWhiteSpace(textbox.Text)); 

Questo sarà afferrare tutte le caselle di testo all'interno di tutti i pannelli in tutte le FlowLayoutPanels nel vostro GroupBox e restituire true se tutti i di quei TextBox hanno un valore in essi.

+0

Perfetto! Grazie mille. C'è un modo in LINQ Posso aggiungere una condizione nella query precedente per filtrare alcune caselle di testo? –

+1

@ this-Me Certo, puoi semplicemente usare la clausola 'Where' di LINQ. Tra l'ultimo 'SelectMany()' e 'All()', prova qualcosa come: '.Where (textbox => textbox.Name.StartsWith (" qualcosa "))' –

3

Uno slution uno di linea,

IEnumerable<TextBox> collection = grpBxTargetSensitivity.Children.OfType<TextBox>(); //assuming you are looking for TextBox 

o

si può provare seguente metodo generico,

public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject 
{ 
    if (depObj != null) 
    { 
     for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) 
     { 
      DependencyObject child = VisualTreeHelper.GetChild(depObj, i); 
      if (child != null && child is T) 
      { 
       yield return (T)child; 
      } 

      foreach (T childOfChild in FindVisualChildren<T>(child)) 
      { 
       yield return childOfChild; 
      } 
     } 
    } 
} 

poi elencare nel corso dei controlli come segue,

foreach (TextBox tb in FindVisualChildren<TextBox>(grpBxTargetSensitivity)) //assuming you are looking for TextBox 
{ 
    // do something 
} 
2

ho creare un metodo per la capacità di trovare eventuali caselle di testo (o di tipo T) e qualsiasi oggetto ereditato da Casella di testo (o di tipo T) per voi:

public static List<T> GetSubControlsOf<T>(Control parent) where T : class 
{ 
     var myCtrls = new List<T>(); 

     foreach (Control ctrl in parent.Controls) 
     { 
      if (ctrl.GetType() == typeof(T) || ctrl.GetType().IsInstanceOfType(typeof(T))) // if ctrl is type of T 
      { 
       myCtrls.Add(ctrl as T); 
      } 
      else if (ctrl.HasChildren) 
      { 
       var childs = GetSubControlsOf<T>(ctrl); 

       if (childs.Any()) myCtrls.AddRange(childs); 
      } 
     } 

     return myCtrls; 
} 

e l'uso che di questo modulo il es:

foreach (var textbox in GetSubControlsOf<TextBox>(this)) 
{ 
     validData &= !string.IsNullOrWhiteSpace(textbox.Text); 
} 
Problemi correlati