2009-03-02 33 views
11

我在页面上有几个Silverlight控件,并且想要查询所有TextBox类型的控件,并使其工作。在Silverlight中查找所有TextBox控件的通用方法

现在我正在使用的Silverlight表格可能已添加更多的TextBox控件。所以,当我测试是否TextBox控件有一个值,我可以这样做:

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

,但我宁愿如果灵活的,我可以用这个任何Silverlight形式,无论TextBox控件的数量我有。

任何想法,我会如何去做呢?

回答

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

实例化的文本框的空列表。调用GetTextBoxes,传递页面上的根控件(在我的情况下,这就是this.LayoutRoot),并且GetTextBoxes应该递归循环遍历每个UI控件的UI元素,测试它是否是TextBox(添加它列表),或者一个小组,可能有它自己的后代来递归。

希望有所帮助。 :)

+0

非常感谢! 这绝对是我一直在寻找的。现在我只需要看看我能否通过UIElement课程获取更多信息。 (即Control x:Name如果可能的话) – coson 2009-03-03 00:23:11

+0

我不认为你可以将`ScrollViewer`作为`Panel`来投射,所以如果你可能需要得到一个的孩子,你需要添加另一个`else` 。 – mbomb007 2015-06-17 16:35:05

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 2009-03-03 00:17:19

+0

你是什么意思? .OfType扩展方法将只返回指定类型的控件。他们将被正确键入。你有什么样的信息? – Ray 2009-03-03 01:09:39

14

我已经遇到这个问题,在这里通知吧:http://megasnippets.com/en/source-codes/silverlight/Get_all_child_controls_recursively_in_Silverlight

这里有一个通用的方法在递归的VisualTree找到所有文本框:

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

使用此方法像这样找到所有文本框:

var textBoxes = GetChildrenRecursively(LayoutRoot).OfType<TextBox>(); 
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; 
    } 
} 
1

类似的逻辑思路上面还处理了“内容”的控制属性等,其中儿童可能被嵌入在较低水平的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; 
    } 
相关问题