2009-05-17 7 views
16

どのようにWPFのウィンドウ内のすべてのコントロールをループするのですか?WPF:ウィンドウ内のすべてのコントロールをループするにはどうすればいいですか?

+2

このリンクは良いスタートかもしれません: http://stackoverflow.com:あなたが答えを見つけることができますhttp://msdn.microsoft.com/en-us/library/bb613556.aspx – VVS

+0

/questions/974598/find-all-controls-in-wpf-window-by-type –

答えて

7

コントロールのすべての子のコンポーネントのリストを取得するクラス:

class Utility 
    { 
     private static StringBuilder sbListControls; 

     public static StringBuilder GetVisualTreeInfo(Visual element) 
     { 
      if (element == null) 
      { 
       throw new ArgumentNullException(String.Format("Element {0} is null !", element.ToString())); 
      } 

      sbListControls = new StringBuilder(); 

      GetControlsList(element, 0); 

      return sbListControls; 
     } 

     private static void GetControlsList(Visual control, int level) 
     { 
      const int indent = 4; 
      int ChildNumber = VisualTreeHelper.GetChildrenCount(control); 

      for (int i = 0; i <= ChildNumber - 1; i++) 
      { 
       Visual v = (Visual)VisualTreeHelper.GetChild(control, i); 

       sbListControls.Append(new string(' ', level * indent)); 
       sbListControls.Append(v.GetType()); 
       sbListControls.Append(Environment.NewLine); 

       if (VisualTreeHelper.GetChildrenCount(v) > 0) 
       { 
        GetControlsList(v, level + 1); 
       } 
      } 
     } 
    } 
+2

論理ツリーをループするのは、ビジュアルツリーをループするよりも効率的です。 – MegaMind

+0

'sbListControls'はローカル変数でなければなりません。これらのメソッドが複数のスレッドによって同時に呼び出された場合に備えてです。 –

14

私はMSDN documenationでこれを見つけたので、それが役立ちます。

// Enumerate all the descendants of the visual object. 
static public void EnumVisual(Visual myVisual) 
{ 
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++) 
    { 
     // Retrieve child visual at specified index value. 
     Visual childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i); 

     // Do processing of the child visual object. 

     // Enumerate children of the child visual object. 
     EnumVisual(childVisual); 
    } 
} 

私はもっとシンプルに見えます。私はフォームでテキストボックスを見つけてデータをクリアするために使っていました。

+0

私はこれに基づいて、実際に 'IEnumerable 'を返すという別の答えを投稿しました。これは、エンドユーザーが通常forループなどを使うことができるようにするためです。 'などを見てください。 – BrainSlugs83

+0

これを再現しようとすると、「.GetChildrenCount(** myVisual **)&.GetChild(** myVisual **、i))」というエラーメッセージが表示され、「Windows.UI.Composition.Visual 'to' 'Windows.UI.Xaml.DependencyObject' "? WPFソリューションはUWP環境で動作しますか?間違った指示(Windows.UI.Composition)を使用していますか? – gaw

0

MSDNの答えに若干のばらつきが...ただそれにビジュアルオブジェクトの空のリストを渡すと、あなたのコレクションは、すべての子ビジュアルが移入されます。この方法では、より優れている

/// <summary> 
/// Enumerate all the descendants (children) of a visual object. 
/// </summary> 
/// <param name="parent">Starting visual (parent).</param> 
/// <param name="collection">Collection, into which is placed all of the descendant visuals.</param> 
public static void EnumVisual(Visual parent, List<Visual> collection) 
{ 
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) 
    { 
     // Get the child visual at specified index value. 
     Visual childVisual = (Visual)VisualTreeHelper.GetChild(parent, i); 

     // Add the child visual object to the collection. 
     collection.Add(childVisual); 

     // Recursively enumerate children of the child visual object. 
     EnumVisual(childVisual, collection); 
    } 
} 
+0

エンドユーザが通常のfor-loopなどを使うことができるように、実際には 'IEnumerable 'を返すあなたの回答に基づいて別の回答を投稿しました。これはリストを作成するオーバーヘッドを節約し、 'break; 'などを見てください。 – BrainSlugs83

8

MSDNメソッドを使用すると、再利用可能で、ループの早期終了が可能になります(つまり、break;など)。forループを最適化し、反復ごとにメソッド呼び出しを保存します。ビジュアルの子をループするための定期的なループ、またはそれが子どもであり、それは壮大な子どもである - それで、消費するのがはるかに簡単です。それを消費する

、あなただけの通常のforeachループを書く(あるいはLINQを使用)することができます

foreach (var ctrl in myWindow.GetChildren()) 
{ 
    // Process children here! 
} 

それとも、再帰しない場合:

foreach (var ctrl in myWindow.GetChildren(false)) 
{ 
    // Process children here! 
} 

それを作るためにこの拡張メソッドを静的クラスに入れるだけで、いつでも好きなときに上記のようなコードを書くことができます:

public static IEnumerable<Visual> GetChildren(this Visual parent, bool recurse = true) 
{ 
    if (parent != null) 
    { 
     int count = VisualTreeHelper.GetChildrenCount(parent); 
     for (int i = 0; i < count; i++) 
     { 
      // Retrieve child visual at specified index value. 
      var child = VisualTreeHelper.GetChild(parent, i) as Visual; 

      if (child != null) 
      { 
       yield return child; 

       if (recurse) 
       { 
        foreach (var grandChild in child.GetChildren(true)) 
        { 
         yield return grandChild; 
        } 
       } 
      } 
     } 
    } 
} 

また、デフォルトで再帰がオンになっていない場合は、拡張メソッドの宣言を変更して、recurse = falseをデフォルトの動作にすることができます。

1

私は以下を使ってすべてのコントロールを取得しました。

public static IList<Control> GetControls(this DependencyObject parent) 
    {    
     var result = new List<Control>(); 
     for (int x = 0; x < VisualTreeHelper.GetChildrenCount(parent); x++) 
     { 
      DependencyObject child = VisualTreeHelper.GetChild(parent, x); 
      var instance = child as Control; 

      if (null != instance) 
       result.Add(instance); 

      result.AddRange(child.GetControls()); 
     } 
     return result; 
    } 
関連する問題