2013-03-03 23 views
9

Tôi muốn thêm một sự kiện cho tất cả các textbox vào mẫu của tôi:Vòng qua tất cả các điều khiển trên một hình thức, ngay cả những người trong groupboxes

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

Vấn đề là chúng được lưu trữ trong một số groupboxes và vòng lặp của tôi không thấy chúng. Tôi có thể lặp qua các điều khiển của từng nhóm riêng lẻ nhưng có thể thực hiện tất cả theo một cách đơn giản trong một vòng lặp không?

+0

Bạn có thể làm điều đó trong một vòng lặp đệ quy. – jac

Trả lời

0

Như bạn đã nói, bạn sẽ phải đi sâu hơn là chỉ đi xe đạp trên từng phần tử trong biểu mẫu của bạn. Điều này, không may, ngụ ý việc sử dụng vòng lặp lồng nhau.

Trong vòng lặp đầu tiên, hãy chuyển qua từng phần tử. NẾU phần tử thuộc loại GroupBox, thì bạn biết bạn sẽ cần phải chu kỳ qua từng phần tử bên trong hộp nhóm, trước khi tiếp tục; hãy thêm sự kiện như bình thường.

Bạn dường như có một nắm bắt tốt về C# vì vậy tôi sẽ không cung cấp cho bạn bất kỳ mã nào; hoàn toàn để đảm bảo bạn phát triển tất cả các khái niệm quan trọng liên quan đến giải quyết vấn đề :)

18

Bộ sưu tập Biểu mẫu và bộ chứa chỉ chứa trẻ em ngay lập tức. Để có được tất cả các điều khiển, bạn cần phải đi qua cây điều khiển và áp dụng hoạt động này một cách đệ quy

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

Lưu ý: Hình thức Xuất phát (gián tiếp) từ Control như tốt và tất cả các điều khiển có một bộ sưu tập Controls. Vì vậy, bạn có thể gọi phương thức như thế này trong hình thức của bạn:

AddTextChangedHandler(this); 

Một giải pháp tổng quát hơn là tạo ra một phương pháp mở rộng áp dụng một hành động một cách đệ quy cho tất cả các điều khiển. Trong một lớp tĩnh (ví dụ WinFormsExtensions) thêm phương pháp này:

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

Không gian tên lớp tĩnh phải "nhìn thấy", nghĩa là, thêm một using khai thích hợp nếu nó là trong không gian tên khác.

Sau đó, bạn có thể gọi nó như thế này, trong đó this là biểu mẫu; bạn cũng có thể thay thế this bởi một hình thức hoặc điều khiển biến mà điều khiển lồng nhau có bị ảnh hưởng:

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

Một vài công cụ đa năng đơn giản làm cho vấn đề này rất đơn giản. Chúng ta có thể tạo ra một phương pháp đơn giản sẽ đi qua cây của toàn bộ cây điều khiển, trả về một chuỗi tất cả các con của nó, tất cả con cái của họ, và vân vân, bao gồm tất cả các điều khiển, không chỉ đến độ sâu cố định. Chúng ta có thể sử dụng đệ quy, nhưng bằng cách tránh đệ quy nó sẽ thực hiện tốt hơn.

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

Sử dụng này, chúng tôi có thể nhận được tất cả các trẻ em, lọc ra những loại chúng tôi cần, và sau đó đính kèm các handler rất dễ dàng:

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

Chưa thấy ai sử dụng LINQ và/hoặc năng suất như vậy ở đây đi:

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

sau đó, bạn có thể sử dụng nó để mong muốn của trái tim của bạn:

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

Hãy thử điều này

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

nơi AllSubControls là

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

LINQ là tuyệt vời!

0

bạn chỉ có thể lặp qua hình thức mở trong cửa sổ hình thức sử dụng bộ sưu tập hình thức ví dụ để thiết lập cửa sổ bắt đầu vị trí cho tất cả các hình thức mở:

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

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

Tôi biết rằng đây là một chủ đề lớn tuổi, nhưng có thể nói mã đoạn trích từ http://backstreet.ch/coding/code-snippets/mit-c-rekursiv-durch-form-controls-loopen/ là một giải pháp thông minh cho vấn đề này.

Nó sử dụng một phương pháp mở rộng cho ControlCollection.

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

Bây giờ, để gán một sự kiện cho tất cả các điều khiển TextBox bạn có thể viết một tuyên bố tương tự (nơi 'này' là hình thức):

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

Tùy chọn bạn có thể lọc các điều khiển bằng thẻ của họ .

Các vấn đề liên quan