2013-03-03 4 views
9

に私は、フォーム上のすべてのテキストボックスにイベントを追加したいと思います:ループ、でもこれらのグループボックス

foreach (Control C in this.Controls) 
{ 
    if (C.GetType() == typeof(System.Windows.Forms.TextBox)) 
    { 
     C.TextChanged += new EventHandler(C_TextChanged); 
    } 
} 

問題は、彼らはいくつかのグループボックスと私のループに格納されていることですそれらを見ることはありません。私は各グループボックスのコントロールを個別にループすることができますが、単純に1つのループですべてを行うことは可能ですか?

+0

再帰的ループで実行できます。 – jac

答えて

0

あなたが述べたように、あなたのフォームの各要素をサイクリングするだけでなく、もっと深く進む必要があります。残念ながら、これはネストされたループの使用を意味します。

最初のループで、各要素を繰り返します。要素がGroupBox型である場合、続行する前に、グループボックス内の各要素を順番に調べる必要があることがわかります。それ以外の場合は、通常通りイベントを追加します。

あなたはC#のまともな把握をしているようですので、私はあなたにコードを与えません。純粋に問題解決に関係するすべての重要な概念を開発できるようにしてください:)

18

Controlsフォームとコンテナコントロールのコレクションには直接の子のみが含まれています。すべてのコントロールを得るために、あなたがコントロールツリーを横断すると、この操作を適用する必要が再帰的に

private void AddTextChangedHandler(Control parent) 
{ 
    foreach (Control c in parent.Controls) 
    { 
     if (c.GetType() == typeof(TextBox)) { 
      c.TextChanged += new EventHandler(C_TextChanged); 
     } else { 
      AddTextChangedHandler(c); 
     } 
    } 
} 

注:同様Controlからフォーム派生(間接的に)と、すべてのコントロールがControlsコレクションを持っています。つまり、あなたの形で、このようなメソッドを呼び出すことができます。

AddTextChangedHandler(this); 

より一般的な解決策は、すべてのコントロールに再帰的にアクションを適用する拡張メソッドを作成することです。静的クラスに(例えばWinFormsExtensions)このメソッドを追加:

public static void ForAllControls(this Control parent, Action<Control> action) 
{ 
    foreach (Control c in parent.Controls) { 
     action(c); 
     ForAllControls(c, action); 
    } 
} 

静的クラスの名前空間は、それが別の名前空間にある場合、すなわち、適切なusing宣言を追加し、「可視」でなければなりません。

次に、このように呼び出すことができます。thisはフォームです。あなたはまた、そのネストされたコントロールの影響を受けるようにしたフォームまたはコントロール変数によってthisを置き換えることができます。

this.ForAllControls(c => 
{ 
    if (c.GetType() == typeof(TextBox)) { 
     c.TextChanged += C_TextChanged; 
    } 
}); 
8

いくつかの簡単な、汎用のツールは、この問題は非常に簡単にします。私たちは、コントロール全体のツリーを横断し、すべてのコントロールをカバーする、すべての子、すべての子などのシーケンスを一定の深さだけでなく返す単純なメソッドを作成できます。再帰を使うこともできますが、再帰を避けることでより良い結果が得られます。

public static IEnumerable<Control> GetAllChildren(this Control root) 
{ 
    var stack = new Stack<Control>(); 
    stack.Push(root); 

    while (stack.Any()) 
    { 
     var next = stack.Pop(); 
     foreach (Control child in next.Controls) 
      stack.Push(child); 
     yield return next; 
    } 
} 

私たちは、子供たちのすべてを取得し、我々が必要とするタイプのものをフィルタリングして、非常に簡単ハンドラを添付することができ、これを使用する:

foreach(var textbox in GetAllChildren().OfType<Textbox>()) 
    textbox.TextChanged += C_TextChanged; 
1

は、LINQを使用して、誰が見ていませんおよび/または収率はそうここに行く:あなたは、あなたの心の欲求にそれを使用することができ

public static class UtilitiesX { 

    public static IEnumerable<Control> GetEntireControlsTree(this Control rootControl) 
    { 
     yield return rootControl; 
     foreach (var childControl in rootControl.Controls.Cast<Control>().SelectMany(x => x.GetEntireControlsTree())) 
     { 
      yield return childControl; 
     } 
    } 

    public static void ForEach<T>(this IEnumerable<T> en, Action<T> action) 
    { 
     foreach (var obj in en) action(obj); 
    } 
} 

someControl.GetEntireControlsTree().OfType<TextBox>().ForEach(x => x.Click += someHandler); 
5

はAllSubControlsが

private static IEnumerable<Control> AllSubControls(Control control) 
    => Enumerable.Repeat(control, 1) 
     .Union(control.Controls.OfType<Control>() 
           .SelectMany(AllSubControls) 
      ); 

LINQは素晴らしいです!あるこの

AllSubControls(this).OfType<TextBox>().ToList() 
    .ForEach(o => o.TextChanged += C_TextChanged); 

をお試しくださいあなたがWindowsフォームで開いているフォームでのみループのウィンドウを設定するために、たとえば、フォームコレクションを使用することができます

0

は、開いているすべてのフォームの開始位置:

public static void setStartPosition() 
     { 
      FormCollection fc = Application.OpenForms; 

      foreach(Form f in fc) 
      { 
       f.StartPosition = FormStartPosition.CenterScreen; 
      } 
     } 
0

私は、これは古い話題であることを知っているが、コードを言うだろうhttp://backstreet.ch/coding/code-snippets/mit-c-rekursiv-durch-form-controls-loopen/のスニペットはこの問題の巧妙な解決策です。

ControlCollectionの拡張メソッドを使用します。

this.Controls.ApplyToAll<TextBox>("", control => 
{ 
    control.TextChanged += SomeEvent 
}); 

は、必要に応じて、あなたがコントロールをそのタグでフィルタリングすることができます:今

public static void ApplyToAll<T>(this Control.ControlCollection controlCollection, string tagFilter, Action action) 
{ 
    foreach (Control control in controlCollection) 
    { 
     if (!string.IsNullOrEmpty(tagFilter)) 
     { 
      if (control.Tag == null) 
      { 
       control.Tag = ""; 
      } 

      if (!string.IsNullOrEmpty(tagFilter) && control.Tag.ToString() == tagFilter && control is T) 
      { 
       action(control); 
      } 
     } 
     else 
     { 
      if (control is T) 
      { 
       action(control); 
      } 
     } 

     if (control.Controls != null && control.Controls.Count > 0) 
     { 
      ApplyToAll(control.Controls, tagFilter, action); 
     } 
    } 
} 

は、あなたが(ここで「これは」形式である)のような文を書くことができ、すべてのTextBoxコントロールにイベントを割り当てます。

関連する問題