2009-03-02 6 views
11

ページに複数のSilverlightコントロールがあり、TextBox型のコントロールをすべて照会し、そのコントロールが必要な場合。SilverlightですべてのTextBoxコントロールを検索する一般的なメソッド

私がで作業しているSilverlightフォームは、にTextBoxコントロールが追加されました。だから私は、TextBoxコントロールが値を持っているならば、私は何ができるかをテストする場合:

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

が、私は関係なく、TextBoxコントロールIの任意の数のSilverlightの形でこれを使用することができます柔軟な場合、私はかなりあるだろう持ってる。

私はそれをどうやってやっていくのですか?しかし、これが唯一の直接の子であるテキストボックスを見つけるあなたは、この(私のグリッドがContentGridと呼ばれている)

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

を行うことができ、あなたの一番上のパネルから

答えて

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要素をループして、TextBoxかどうかをテストしますそのパネルの子孫が再帰的に通過する可能性があります)。

希望に役立ちます。 http://megasnippets.com/en/source-codes/silverlight/Get_all_child_controls_recursively_in_Silverlight

ここでは、VisualTreeに再帰的にすべてのTextBoxを見つけるために、汎用的な方法があります:

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

は、このように、この方法を使用し、私はすでにこの問題に直面し、それをここに通知してきた:)

+0

多くのありがとう! これは間違いなく私が探していたものです。これで、UIElementクラスを使用して詳細情報を抽出できるかどうかを確認するだけです。 (コントロールx:可能であればName) – coson

+0

'ScrollViewer'を' Panel'としてキャストすることはできないと思いますので、もしあなたがその子を取得する必要があるならば、 'else'を追加する必要があります。 – mbomb007

3

。以下のような再帰のいくつかの並べ替えが役立つだろうが、私は良い方法がなければならないと考えている。

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

すべてのTextBoxを見つける:

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

VB.Netと同じコード:共有共有関数GetChildsRecursive(ByVal Root As DependencyObject)IEnumerable(Of DependencyObject)が新しいリスト(Of DependencyObject)として見つかりませんFound.Add(Root)For i As Integer = 0 To VisualTreeHelper.GetChildrenCount Root) - 1 Found.AddRange(GetChildsRecursive(VisualTreeHelper.GetChild(Root、i)))次の戻り値の最後の関数を返します – Christoph

3

Scott'sinitial ideaを取り、それを拡大しているので、それを

  1. ジェネリックを使用するので、複数のコントロールタイプに簡単に対応できます。
  2. より多くのコンテナタイプをサポートしています。私のWP7では、私はpanaorama、scroll viewerなどをサポートする必要がありました。これはパネルではありません。したがって、これはそれらのサポートを可能にします。
  3. 最大の問題は、特にPanelとderrivedアイテムで比較される文字列です。

コード:

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

グリッドがPanelを継承します –

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; 
    } 
関連する問題