2009-03-02 13 views
11

Ho diversi controlli Silverlight su una pagina e voglio interrogare tutti i controlli che sono di tipo TextBox e farlo funzionare.Metodo generico per trovare tutti i controlli TextBox in Silverlight

Ora il modulo Silverlight su cui sto lavorando potrebbe più controlli TextBox aggiunti. Così, quando ho test per vedere se un controllo TextBox ha un valore, che potevo fare:

if (this.TextBox.Control.value.Text() != String.Empty) 
{ 
    // do whatever 
} 

ma preferirei avere se flessibile che posso usare questo su qualsiasi forma di Silverlight, indipendentemente dal numero di controlli TextBox I avere.

Qualche idea su come farei per farlo?

risposta

10

suona come avete bisogno di un ricorsivo routine, come GetTextBoxes qui sotto:

void Page_Loaded(object sender, RoutedEventArgs e) 
{ 
    // Instantiate a list of TextBoxes 
    List<TextBox> textBoxList = new List<TextBox>(); 

    // Call GetTextBoxes function, passing in the root element, 
    // and the empty list of textboxes (LayoutRoot in this example) 
    GetTextBoxes(this.LayoutRoot, textBoxList); 

    // Now textBoxList contains a list of all the text boxes on your page. 
    // Find all the non empty textboxes, and put them into a list. 
    var nonEmptyTextBoxList = textBoxList.Where(txt => txt.Text != string.Empty).ToList(); 

    // Do something with each non empty textbox. 
    nonEmptyTextBoxList.ForEach(txt => Debug.WriteLine(txt.Text)); 
} 

private void GetTextBoxes(UIElement uiElement, List<TextBox> textBoxList) 
{ 
    TextBox textBox = uiElement as TextBox; 
    if (textBox != null) 
    { 
     // If the UIElement is a Textbox, add it to the list. 
     textBoxList.Add(textBox); 
    } 
    else 
    { 
     Panel panel = uiElement as Panel; 
     if (panel != null) 
     { 
      // If the UIElement is a panel, then loop through it's children 
      foreach (UIElement child in panel.Children) 
      { 
       GetTextBoxes(child, textBoxList); 
      } 
     } 
    } 
} 

un'istanza di una lista vuota di caselle di testo. Chiama GetTextBoxes, passando il controllo di root sulla tua pagina (nel mio caso, questo è this.LayoutRoot), e GetTextBoxes dovrebbe ricorsivamente in loop attraverso ogni elemento dell'interfaccia utente che è un discendente di quel controllo, testando se è un TextBox (aggiungilo alla lista), o un pannello, che potrebbe avere dei discendenti di cui è il proprietario a recitare.

Spero che questo aiuti. :)

+0

Molte grazie! Questo è sicuramente quello che stavo cercando. Ora ho solo bisogno di vedere se posso la classe UIElement per estrarre più informazioni. (es. Controllo x: Nome se possibile) – coson

+0

Non penso tu possa lanciare un 'ScrollViewer' come un' Panel', quindi se potresti aver bisogno di prenderne uno figlio, dovrai aggiungere un altro 'else' . – mbomb007

3

Dalla cima più pannello si può fare questo (la mia griglia è chiamato ContentGrid)

var textBoxes = this.ContentGrid.Children.OfType<TextBox>(); 
var nonEmptyTextboxes = textBoxes.Where(t => !String.IsNullOrEmpty(t.Text)); 
foreach (var textBox in nonEmptyTextboxes) 
{ 
    //Do Something 
} 

Tuttavia questo troverete solo i caselle di testo che sono figli diretti. Una sorta di ricorsione come quella in basso sarebbe d'aiuto, ma penso che ci debba essere un modo migliore.

private List<TextBox> SearchForTextBoxes(Panel panel) 
{ 
    List<TextBox> list = new List<TextBox>(); 
    list.AddRange(panel.Children.OfType<TextBox>() 
     .Where(t => !String.IsNullOrEmpty(t.Text))); 

    var panels = panel.Children.OfType<Panel>(); 
    foreach (var childPanel in panels) 
    { 
     list.AddRange(SearchForTextBoxes(childPanel)); 
    } 
    return list; 
} 
+0

Questo è sicuramente un passo nella giusta direzione. Esiste un modo per utilizzare Reflection per ottenere informazioni su un controllo se si tratta di un determinato tipo di controllo? – coson

+0

Cosa intendi? Il metodo di estensione .OfType restituirà solo i controlli del tipo specificato. E verranno digitati correttamente. Che tipo di informazioni stai cercando? – Ray

14

Ho già affrontato questo problema e notificare qui: http://megasnippets.com/en/source-codes/silverlight/Get_all_child_controls_recursively_in_Silverlight

Qui avete un metodo generico per trovare in modo ricorsivo nel VisualTree tutte le caselle di testo:

IEnumerable<DependencyObject> GetChildrenRecursively(DependencyObject root) 
{ 
    List<DependencyObject> children = new List<DependencyObject>(); 
    children.Add(root); 
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++) 
     children.AddRange(GetChildrenRecursively(VisualTreeHelper.GetChild(root, i))); 

    return children; 
} 

utilizzare questo metodo come questo per trovare tutti TextBoxes:

var textBoxes = GetChildrenRecursively(LayoutRoot).OfType<TextBox>(); 
+0

Stesso codice di VB.Net:Public Shared Function GetChildsRecursive (ByVal Root As DependencyObject) As IEnumerable (Of DependencyObject) Dim Trovato come nuovo elenco (Of DependencyObject) Found.Add (Root) Per i As Integer = 0 To VisualTreeHelper.GetChildrenCount (Root) - 1 Found.AddRange (GetChildsRecursive (VisualTreeHelper.GetChild (Root, i))) Next Return Found End Function – Christoph

3

ha preso Scott'sinitial idea e ampliato in modo che esso

  1. Utilizza generici, quindi gestisce facilmente più tipi di controllo.
  2. Supporta più tipi di contenitori. Nel mio WP7 avevo bisogno di supportare panaorama, scroll viewer ecc ... che non sono pannelli. Quindi questo consente il supporto per loro.
  3. Il problema più grosso è il confronto delle stringhe, in particolare sul pannello e sugli articoli in sospensione.

Codice:

private static void GetControls<T>(UIElement uiElement, List<T> controlList) where T : UIElement 
{ 
    var frameworkFullName = uiElement.GetType().FullName; 
    if (frameworkFullName == typeof(T).FullName) 
    { 
     controlList.Add(uiElement as T); 
     return; 
    } 

    if (frameworkFullName == typeof(Panel).FullName || 
     frameworkFullName == typeof(Grid).FullName || 
     frameworkFullName == typeof(StackPanel).FullName) 
    { 
     foreach (var child in (uiElement as Panel).Children) 
     { 
      GetControls(child, controlList); 
     } 
     return; 
    } 

    if (frameworkFullName == typeof(Panorama).FullName) 
    { 
     foreach (PanoramaItem child in (uiElement as Panorama).Items) 
     { 
      var contentElement = child.Content as FrameworkElement; 
      if (contentElement != null) 
      { 
       GetControls(contentElement, controlList); 
      } 
     } 
     return; 
    } 

    if (frameworkFullName == typeof(ScrollViewer).FullName) 
    { 
     var contentElement = (uiElement as ScrollViewer).Content as FrameworkElement; 
     if (contentElement != null) 
     { 
      GetControls(contentElement, controlList); 
     } 
     return; 
    } 
} 
+0

Pannello di ereditarietà della griglia –

1

logica simile a idee di cui sopra per gestire anche i controlli con un "Contenuto" attributo come TabItems e Scrollviewers dove i bambini potrebbero essere incorporati a un livello inferiore.Trova tutti i bambini:

IEnumerable<DependencyObject> GetControlsRecursive(DependencyObject root) 
    { 
     List<DependencyObject> elts = new List<DependencyObject>(); 
     elts.Add(root); 
     string type = root.GetType().ToString().Replace("System.Windows.Controls.", ""); 
     switch (root.GetType().ToString().Replace("System.Windows.Controls.", "")) 
     { 
      case "TabItem": 
       var TabItem = (TabItem)root; 
       elts.AddRange(GetControlsRecursive((DependencyObject)TabItem.Content)); 
       break; 
      case "ScrollViewer": 
       var Scroll = (ScrollViewer)root; 
       elts.AddRange(GetControlsRecursive((DependencyObject) Scroll.Content)); 
       break; 
      default: //controls that have visual children go here 
       for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++) elts.AddRange(GetControlsRecursive(VisualTreeHelper.GetChild(root, i))); 
       break; 
     } 
     return elts; 
    } 
Problemi correlati