2009-03-02 26 views
11

Tengo varios controles Silverlight en una página y quiero consultar todos los controles que son de tipo TextBox y que funcionen.Método genérico para encontrar todos los controles TextBox en Silverlight

Ahora la forma Silverlight estoy trabajando en podía tienen más controles de cuadro de texto añadido. Así que cuando me prueba para ver si un control TextBox tiene un valor, que podía hacer:

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

pero prefiero tener si flexibles que puedo usar esto en cualquier forma Silverlight, independientemente del número de controles TextBox I tener.

Alguna idea sobre cómo voy a hacer eso?

Respuesta

10

Parece que necesita un recursiva de rutina, como GetTextBoxes siguientes:

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 una lista vacía de cuadros de texto. Llamar a GetTextBoxes, pasando el control raíz en su página (en mi caso, eso es esto. LayoutRoot), y GetTextBoxes deberían recorrer recursivamente cada elemento de UI que es un descendiente de ese control, probando para ver si es un TextBox (agréguelo) a la lista), o un panel, que podría tener descendientes propios para recurrir a través de.

Espero que ayude. :)

+0

¡Muchas gracias! Esto es definitivamente lo que estaba buscando. Ahora solo necesito ver si puedo usar la clase UIElement para extraer más información. (es decir, Control x: Nombre si es posible) – coson

+0

No creo que pueda convertir un 'ScrollViewer' como un' Panel', por lo que si necesita obtener el elemento secundario de uno, deberá agregar otro 'else' . – mbomb007

3

Desde su parte superior la mayor parte del panel se puede hacer esto (mi rejilla se llama ContentGrid)

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

Sin embargo, esto sólo encontrará los cuadros de texto que son hijos inmediatos. Algún tipo de recursividad como la siguiente ayudaría, pero estoy pensando que debe haber una mejor manera.

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

Esto es definitivamente un paso en la dirección correcta. ¿Existe alguna forma de usar Reflection para obtener información sobre un control si se trata de un tipo de control determinado? – coson

+0

¿Qué quieres decir? El método de extensión .OfType solo devolverá controles del tipo especificado. Y se escribirán correctamente. ¿Qué tipo de información estás buscando? – Ray

14

que ya se han enfrentado a este problema y notificar aquí: http://megasnippets.com/en/source-codes/silverlight/Get_all_child_controls_recursively_in_Silverlight

Aquí tienen un método genérico para encontrar de forma recursiva en el VisualTree todos los cuadros de texto:

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

utilizar este método como este para encontrar todos los cuadros de texto:

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

Mismo código que VB.Net:Public Shared Function GetChildsRecursive (ByVal Root As DependencyObject) Como IEnumerable (Of DependencyObject) Dim Encontrada como Nueva lista (Of DependencyObject) Found.Add (Root) For i As Integer = 0 To VisualTreeHelper.GetChildrenCount (Root) - 1 Found.AddRange (GetChildsRecursive (VisualTreeHelper.GetChild (Root, i))) Siguiente Volver Found End Función – Christoph

3

Tomó Scott'sinitial idea y lo amplió para que

  1. Utiliza genéricos, por lo que se adapta fácilmente a múltiples tipos de control.
  2. Admite más tipos de contenedores. En mi WP7 necesitaba apoyar panaorama's, scroll viewers, etc ... que no son Paneles. Entonces esto les permite apoyo.
  3. El mayor problema es la comparación de cadenas, especialmente en el Panel y los elementos derivados.

Código:

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

La cuadrícula hereda el Panel –

1

lógica similar a las ideas por encima de manejar también los controles con un "contenido" como atributo TabItems y Scrollviewers donde los niños pueden estar incrustados en un nivel inferior.Encuentra todos los niños:

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