2010-04-29 11 views
6

Ho un Form denominato A.Come si ottengono tutti i controlli di un modulo in Windows Form?

A contiene molti controlli diversi, incluso uno GroupBox principale. Questo GroupBox contiene molte tabelle e altri GroupBox es. Voglio trovare un controllo che ha per es. scheda indice 9 nel modulo A, ma non so quale GroupBox contenga questo controllo.

Come posso fare questo?

+0

Mi piacerebbe utilizzare il metodo di estensione Map di Marc per questo tipo di ricorsione: http://stackoverflow.com/questions/141467/recursive-list-flattening/229442#229442 – Oliver

risposta

4

Cerca in modo ricorsivo nella raccolta Controls del modulo.

void FindAndSayHi(Control control) 
{ 
    foreach (Control c in control.Controls) 
    { 
     Find(c.Controls); 
     if (c.TabIndex == 9) 
     { 
      MessageBox.Show("Hi"); 
     } 
    } 
} 
1
void iterateControls(Control ctrl) 
{ 
    foreach(Control c in ctrl.Controls) 
    { 
     iterateControls(c); 
    } 
} 
2

si può fare un metodo come questo:

public static Control GetControl(Control.ControlCollection controlCollection, Predicate<Control> match) 
{ 
    foreach (Control control in controlCollection) 
    { 
     if (match(control)) 
     { 
      return control; 
     } 

     if (control.Controls.Count > 0) 
     { 
      Control result = GetControl(control.Controls, match); 
      if (result != null) 
      { 
       return result; 
      } 
     } 
    } 

    return null; 
} 

... che viene usato in questo modo:

Control control = GetControl(this.Controls, ctl => ctl.TabIndex == 9); 

Nota tuttavia che TabIndex è un caso difficile, poiché inizia da 0 all'interno di ciascun contenitore, quindi potrebbero esserci più controlli nella stessa forma che hanno lo stessoValore.

In entrambi i casi, il metodo di cui sopra può essere utilizzato per il controllo di praticamente qualsiasi proprietà dei controlli:

Control control = GetControl(this.Controls, ctl => ctl.Text == "Some text"); 
13

Con la ricorsione ...

public static IEnumerable<T> Descendants<T>(this Control control) where T : class 
{ 
    foreach (Control child in control.Controls) { 

     T childOfT = child as T; 
     if (childOfT != null) { 
      yield return (T)childOfT; 
     } 

     if (child.HasChildren) { 
      foreach (T descendant in Descendants<T>(child)) { 
       yield return descendant; 
      } 
     } 
    } 
} 

È possibile utilizzare la funzione di cui sopra, come:

var checkBox = (from c in myForm.Descendants<CheckBox>() 
       where c.TabIndex == 9 
       select c).FirstOrDefault(); 

Che otterrà il primo CheckBox ovunque all'interno del modulo che ha un TabInde x di 9. Ovviamente puoi usare qualunque criterio tu voglia.

Se non sei un fan di LINQ sintassi di query, quanto sopra potrebbe essere riscritto come:

var checkBox = myForm.Descendants<CheckBox>() 
        .FirstOrDefault(x=>x.TabIndex==9); 
+0

Wow, questo è un estremo, Modo troppo complicato per trovare un controllo con un indice di tabulazione di 9. Kudos per lo sforzo però. –

+2

Il metodo trova un controllo solo con un indice di tabulazione 9. Il mio è un metodo di estensione che abilita in modo efficace LINQ a WinForms. È lo stesso approccio utilizzato da LINQ in XML. Ed è difficilmente complicato, è una semplice ricorsione come molte altre risposte. L'unica differenza è che sto filtrando sul tipo che rende il predicato più facile da scrivere. – Josh

+0

Ok, posso aggiungere un parametro int e ora lo fa.Seriamente però, non ne avrai mai bisogno, devi solo trovare un controllo con un indice di tabulazione uguale a n, e le persone devono fissarlo per almeno qualche secondo per capire cosa fa. Inoltre, preferirei scrivere Find (questo, 9) invece di una query, ma non volevo essere scortese, dopotutto questo è un posto per divertirsi un po 'con il codice. –

0

Odio la ricorsione, così ho sempre usare una pila per questo genere di cose. Questo assegna un gestore di eventi comuni alla CheckedChanged caso di ogni controllo RadioButton nella gerarchia di controllo della corrente:

Stack<Control> controlStack = new Stack<Control>(); 
foreach (Control c in this.Controls) 
{ 
    controlStack.Push(c); 
} 
Control ctl; 
while (controlStack.Count > 0 && (ctl = controlStack.Pop()) != null) 
{ 
    if (ctl is RadioButton) 
    { 
     (ctl as RadioButton).CheckedChanged += new EventHandler(rb_CheckedChanged); 
    } 
    foreach (Control child in ctl.Controls) 
    { 
     controlStack.Push(child); 
    } 
} 

Si potrebbe facilmente retrofit metodo di estensione di Josh Einstein a lavorare in questo modo.

Problemi correlati