2009-03-02 3 views
11

У меня есть несколько элементов управления Silverlight на странице и вы хотите запросить все элементы управления типа TextBox и работать с ними.Общий метод поиска всех элементов управления TextBox в Silverlight

Теперь форма Silverlight Я работаю над может добавить больше элементов управления TextBox. Поэтому, когда я тест, чтобы увидеть, если элемент управления TextBox имеет значение, я мог бы сделать:

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

, но я бы предпочел, если гибок, что я могу использовать это на любом Silverlight форме независимо от количества элементов управления TextBox I иметь.

Любые идеи о том, как я буду это делать?

ответ

10

Это звучит, как вам нужно рекурсивный рутина, как GetTextBoxes ниже:

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 пустой список TextBoxes. Вызовите GetTextBoxes, перейдя в корневой элемент управления на вашей странице (в моем случае, это this.LayoutRoot), и GetTextBoxes должны рекурсивно прокручивать каждый элемент пользовательского интерфейса, который является потомком этого элемента управления, тестируя его, будь то TextBox (добавьте его к списку), или панель, у которой могут быть потомки ее собственных, чтобы пройти через нее.

Надеюсь, что это поможет. :)

+0

Большое спасибо! Это определенно то, что я искал. Теперь мне просто нужно выяснить, могу ли я использовать класс UIElement для получения дополнительной информации. (т. е. Control x: Name, если это возможно) – coson

+0

Я не думаю, что вы можете использовать 'ScrollViewer' как' Panel', поэтому, если вам может понадобиться получить дочерний элемент из одного, вам нужно будет добавить еще один 'else' , – mbomb007

3

С вашей верхней панели большинства вы можете сделать это (моя сетка называется ContentGrid)

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

Однако это будет только найти текстовые поля, которые являются непосредственными потомками. Некоторая рекурсия, как показано ниже, поможет, но я думаю, что должен быть лучший способ.

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

Это, безусловно, шаг в правильном направлении. Есть ли способ использовать Reflection для получения информации об элементе управления, если это определенный тип управления? – coson

+0

Что значит? Метод расширения .OfType будет возвращать только элементы управления указанного типа. И они будут напечатаны правильно. Какую информацию вы используете? – Ray

14

Я уже сталкивался с этим вопросом и уведомить его здесь: http://megasnippets.com/en/source-codes/silverlight/Get_all_child_controls_recursively_in_Silverlight

Здесь у вас есть универсальный метод, чтобы найти рекурсивно в VisualTree все 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; 
} 

Используйте этот метод, как это найти все TextBoxes:

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

Тот же код, что и VB.Net: Общая публичная функция GetChildsRecursive (ByVal Root As DependencyObject) Поскольку IEnumerable (Of DependencyObject) Dim Найден как новый список (DependencyObject) Found.Add (Root) Для i As Integer = 0 Для VisualTreeHelper.GetChildrenCount (Root) - 1 Найдено.AddRange (GetChildsRecursive (VisualTreeHelper.GetChild (Root, i))) Next Return Found End Function – Christoph

3

Принимал Scott'sinitial idea и расширил ее так, чтобы она

  1. Использует дженерики, поэтому он легко справляется с несколькими типами управления.
  2. Поддерживает больше типов контейнеров. В моей WP7 мне нужно было поддерживать зрителей panaorama, прокрутки и т. Д. ... которые не являются панелями. Таким образом, это позволяет поддерживать их.
  3. Самая большая проблема заключается в том, что сравнение строк, особенно на панели и выносливых элементах.

Код:

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

Grid inherits Panel –

1

Аналогичная логика идей выше, также обрабатывать управления с «Content» атрибут как TabItems и Scrollviewers, где дети могут быть внедрены на более низком уровне.Находит всех детей:

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; 
    } 
Смежные вопросы