2009-03-02 13 views
11

J'ai plusieurs contrôles Silverlight sur une page et je veux interroger tous les contrôles qui sont de type TextBox et qui fonctionnent.Méthode générique pour trouver tous les contrôles TextBox dans Silverlight

Maintenant le formulaire Silverlight que je travaille sur pourrait avoir plus de contrôles TextBox ajouté. Alors, quand je test pour voir si un contrôle TextBox a une valeur, que je pouvais faire:

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

mais je préfère avoir si souple que je peux utiliser toute forme Silverlight quel que soit le nombre de contrôles TextBox I avoir.

Des idées sur comment j'irais faire ça?

Répondre

10

Il semble que vous avez besoin d'une routine récursive comme GetTextBoxes ci-dessous:

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); 
      } 
     } 
    } 
} 

Instantiate une liste vide de TextBoxes. Appelez GetTextBoxes, en passant le contrôle racine sur votre page (dans mon cas, c'est this.LayoutRoot), et GetTextBoxes doit parcourir récursivement chaque élément de l'interface utilisateur qui est un descendant de ce contrôle, test pour voir s'il s'agit d'un TextBox (ajoutez-le à la liste), ou un panneau, qui pourrait avoir des descendants de son propre à recurse à travers.

Espérons que ça aide. :)

+0

Merci beaucoup! C'est vraiment ce que je cherchais. Maintenant, j'ai juste besoin de voir si je peux la classe UIElement pour extraire plus d'informations. (ie Contrôlez x: Nom si possible) – coson

+0

Je ne pense pas que vous puissiez lancer un 'ScrollViewer' en tant que' Panel', donc si vous avez besoin d'un enfant, vous devrez en ajouter un autre 'else' . – mbomb007

3

À partir de votre panneau le plus haut que vous pouvez le faire (ma grille est appelée ContentGrid)

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

Cependant, cela ne trouverez que les zones de texte qui sont des enfants immédiats. Une sorte de récursion comme ci-dessous pourrait aider, mais je pense qu'il doit y avoir un meilleur moyen.

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

Ceci est certainement un pas dans la bonne direction. Existe-t-il un moyen d'utiliser Reflection pour obtenir des informations sur un contrôle s'il s'agit d'un certain type de contrôle? – coson

+0

Que voulez-vous dire? La méthode d'extension .OfType ne renvoie que les contrôles du type spécifié. Et ils seront tapés correctement. Quel genre d'information es-tu après? – Ray

14

J'ai déjà fait face à cette question et en informe ici: http://megasnippets.com/en/source-codes/silverlight/Get_all_child_controls_recursively_in_Silverlight

Ici vous avez une méthode générique pour trouver récursive dans le VisualTree tous TextBoxes:

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; 
} 

Utilisez cette méthode comme celle-ci trouver toutes les zones de texte:

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

code Identique à VB.Net:Public partagée Fonction GetChildsRecursive (ByVal racine DependencyObject) Comme IEnumerable (Of DependencyObject) Dim Trouvé As New List (Of DependencyObject) Found.Add (Racine) pour i As Integer = 0 Pour VisualTreeHelper.GetChildrenCount (root) - 1 Found.AddRange (GetChildsRecursive (VisualTreeHelper.GetChild (root, i))) Suivant Retour trouvée End Function – Christoph

3

A pris Scott'sinitial idea et étendu afin qu'il

  1. Utilise des génériques, ce qui lui permet de gérer facilement plusieurs types de contrôle.
  2. Prise en charge de plusieurs types de conteneur. Dans mon WP7, j'avais besoin de supporter les panaorama, les visionneuses de défilement etc ... qui ne sont pas des Panels. Donc, cela permet un soutien pour eux.
  3. Le plus gros problème est la comparaison de chaînes, en particulier sur le Panel et les articles dérivés.

code:

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

Grille hérite panneau –

1

Une logique similaire aux idées ci-dessus pour traiter également les commandes avec un « contenu » attribut comme TabItems et Scrollviewers où les enfants pourraient être intégrés à un niveau inférieur.Trouve tous les enfants:

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; 
    } 
Questions connexes