2009-05-17 16 views
16

Come faccio a scorrere tutti i controlli in una finestra in WPF?WPF: Come faccio a scorrere tutti i controlli in una finestra?

+2

Questo link potrebbe essere un buon punto di partenza: http://msdn.microsoft.com/en-us/library/bb613556.aspx – VVS

+0

si può trovare la risposta in: http://stackoverflow.com/questions/974598/find-all-controls-in-wpf-window-by-type –

risposta

7

classe per ottenere una lista di tutti i componenti dei bambini di un controllo:

class Utility 
    { 
     private static StringBuilder sbListControls; 

     public static StringBuilder GetVisualTreeInfo(Visual element) 
     { 
      if (element == null) 
      { 
       throw new ArgumentNullException(String.Format("Element {0} is null !", element.ToString())); 
      } 

      sbListControls = new StringBuilder(); 

      GetControlsList(element, 0); 

      return sbListControls; 
     } 

     private static void GetControlsList(Visual control, int level) 
     { 
      const int indent = 4; 
      int ChildNumber = VisualTreeHelper.GetChildrenCount(control); 

      for (int i = 0; i <= ChildNumber - 1; i++) 
      { 
       Visual v = (Visual)VisualTreeHelper.GetChild(control, i); 

       sbListControls.Append(new string(' ', level * indent)); 
       sbListControls.Append(v.GetType()); 
       sbListControls.Append(Environment.NewLine); 

       if (VisualTreeHelper.GetChildrenCount(v) > 0) 
       { 
        GetControlsList(v, level + 1); 
       } 
      } 
     } 
    } 
+2

Il looping attraverso l'albero logico non è migliore e più efficace del loop attraverso l'albero visivo. – MegaMind

+0

'sbListControls' dovrebbe essere una variabile locale, nel caso in cui questi metodi vengano chiamati contemporaneamente da più thread. –

14

ho trovato questo nel MSDN documenation in modo che aiuta.

// Enumerate all the descendants of the visual object. 
static public void EnumVisual(Visual myVisual) 
{ 
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++) 
    { 
     // Retrieve child visual at specified index value. 
     Visual childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i); 

     // Do processing of the child visual object. 

     // Enumerate children of the child visual object. 
     EnumVisual(childVisual); 
    } 
} 

Sembra più semplice per me. L'ho usato per trovare caselle di testo in un modulo e cancellare i loro dati.

+0

Ho pubblicato un'altra risposta basata su questo che restituisce effettivamente un 'IEnumerable ' in modo che l'utente finale possa semplicemente utilizzare un ciclo regolare, ecc. Ciò rende molto semplice l'enumerazione della raccolta figli e consente l'aborto anticipato tramite 'break; 'ecc. Dai un'occhiata. – BrainSlugs83

+0

Quando provo a riprodurlo, viene visualizzato un errore su myVisual (ad esempio .GetChildrenCount (** myVisual **) & .GetChild (** myVisual **, i)) che dice "impossibile convertire da" Windows.UI.Composition.Visual 'a' Windows.UI.Xaml.DependencyObject '"? Le soluzioni WPF funzionano nell'ambiente UWP? Sto usando la direttiva using errata (Windows.UI.Composition)? – gaw

0

Una leggera variazione della risposta MSDN ... basta passare in un vuoto elenco di oggetti visivi in ​​esso e la vostra collezione sarà popolata con tutte le immagini del bambino:

/// <summary> 
/// Enumerate all the descendants (children) of a visual object. 
/// </summary> 
/// <param name="parent">Starting visual (parent).</param> 
/// <param name="collection">Collection, into which is placed all of the descendant visuals.</param> 
public static void EnumVisual(Visual parent, List<Visual> collection) 
{ 
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) 
    { 
     // Get the child visual at specified index value. 
     Visual childVisual = (Visual)VisualTreeHelper.GetChild(parent, i); 

     // Add the child visual object to the collection. 
     collection.Add(childVisual); 

     // Recursively enumerate children of the child visual object. 
     EnumVisual(childVisual, collection); 
    } 
} 
+0

Ho pubblicato un'altra risposta basata sul tuo che restituisce effettivamente un 'IEnumerable ' in modo che l'utente finale possa semplicemente utilizzare un ciclo regolare, ecc. Ciò consente di risparmiare l'overhead della creazione di un elenco e consente l'aborto anticipato tramite 'break; 'ecc. Dai un'occhiata. – BrainSlugs83

8

In questo modo è superiore al Metodo MSDN, in quanto riutilizzabile e consente l'interruzione anticipata del ciclo (ad esempio tramite, break;, ecc.), Ottimizza il ciclo for in quanto salva una chiamata al metodo per ogni iterazione e consente inoltre di utilizzare regolare per cicli di loop attraverso i figli di un Visual, o anche recitare i suoi figli ed è grandioso - quindi è molto più semplice da consumare.

Per consumarlo, si può semplicemente scrivere un ciclo foreach regolare (o anche usare LINQ):

foreach (var ctrl in myWindow.GetChildren()) 
{ 
    // Process children here! 
} 

O se non si vuole ricorsione:

foreach (var ctrl in myWindow.GetChildren(false)) 
{ 
    // Process children here! 
} 

Per rendere più lavoro, basta mettere questo metodo di estensione in qualsiasi classe statica, quindi sarete in grado di scrivere codice simile al momento di cui sopra che ti piace:

public static IEnumerable<Visual> GetChildren(this Visual parent, bool recurse = true) 
{ 
    if (parent != null) 
    { 
     int count = VisualTreeHelper.GetChildrenCount(parent); 
     for (int i = 0; i < count; i++) 
     { 
      // Retrieve child visual at specified index value. 
      var child = VisualTreeHelper.GetChild(parent, i) as Visual; 

      if (child != null) 
      { 
       yield return child; 

       if (recurse) 
       { 
        foreach (var grandChild in child.GetChildren(true)) 
        { 
         yield return grandChild; 
        } 
       } 
      } 
     } 
    } 
} 

Inoltre, se la ricorsione non è attiva per impostazione predefinita, è possibile modificare la dichiarazione del metodo di estensione in modo che il comportamento predefinito sia recurse = false.

1

Ho usato quanto segue per ottenere tutti i controlli.

public static IList<Control> GetControls(this DependencyObject parent) 
    {    
     var result = new List<Control>(); 
     for (int x = 0; x < VisualTreeHelper.GetChildrenCount(parent); x++) 
     { 
      DependencyObject child = VisualTreeHelper.GetChild(parent, x); 
      var instance = child as Control; 

      if (null != instance) 
       result.Add(instance); 

      result.AddRange(child.GetControls()); 
     } 
     return result; 
    } 
Problemi correlati