2009-03-02 37 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; 
    } 
相關問題