2011-01-07 2 views
29

У меня есть несколько картинных ящиков, и мне нужно загрузить в них случайные изображения во время работы. Поэтому я подумал, что было бы неплохо иметь коллекцию всех графических ящиков, а затем назначать изображения им с помощью простого цикла. Но как мне это сделать? Или, может быть, есть ли другие более эффективные решения этой проблемы?Получить все элементы управления определенного типа

ответ

61

Использование немного LINQ:

foreach(var pb in this.Controls.OfType<PictureBox>()) 
{ 
    //do stuff 
} 

Однако, это займет только забота о PictureBoxes в главном контейнере.

+16

Это не будет рассматривать PictureBoxes, которые вложены в другие контейнеры. – cdhowie

+0

В качестве альтернативы ... Еогеасп (PictureBox рь в this.Controls.OfType ()) { // делать вещи } Не уверен, что это имеет огромное значение, но я, как правило, отдают предпочтение явного объявления , – Scooter

+0

Что-то вроде этого: https: // stackoverflow.com/questions/47182809/how-to-count-the-checkboxes-in-asp-net-form/47182982 # 47182982 – Si8

19

Вы можете использовать этот метод:

public static IEnumerable<T> GetControlsOfType<T>(Control root) 
    where T : Control 
{ 
    var t = root as T; 
    if (t != null) 
     yield return t; 

    var container = root as ContainerControl; 
    if (container != null) 
     foreach (Control c in container.Controls) 
      foreach (var i in GetControlsOfType<T>(c)) 
       yield return i; 
} 

Тогда вы могли бы сделать что-то вроде этого:

foreach (var pictureBox in GetControlsOfType<PictureBox>(theForm)) { 
    // ... 
} 
+1

Я думаю, что это на самом деле более словнее, чем просто 'root.Controls.OfType '. –

+5

О, я вижу, вы дошли до бесконечной глубины. Попался. –

+0

не совсем Дэн Тао, если PictureBox находится в дополнительном контейнере, версия LINQ не получит его. – Femaref

7

Если вы по крайней мере на .NET 3.5, то у вас есть LINQ, что означает, что поскольку ControlCollection реализует IEnumerable вы можете просто сделать:

var pictureBoxes = Controls.OfType<PictureBox>(); 
+3

Это не будет учитывать PictureBoxes, которые вложены в другие контейнеры. – cdhowie

+2

Право. В моей защите ОП не уточнил, было ли это требование; но тем не менее, было бы разумно рассматривать его как таковое. –

1

Я использую этот GENERI c рекурсивный метод:

Предполагается, что если элемент управления имеет значение T, то метод не выглядит в его дочерних элементах. Если вам нужно также посмотреть на своих детей, вы можете легко изменить его соответствующим образом.

public static IList<T> GetAllControlsRecusrvive<T>(Control control) where T :Control 
{ 
    var rtn = new List<T>(); 
    foreach (Control item in control.Controls) 
    { 
     var ctr = item as T; 
     if (ctr!=null) 
     { 
      rtn.Add(ctr); 
     } 
     else 
     { 
      rtn.AddRange(GetAllControlsRecusrvive<T>(item)); 
     } 

    } 
    return rtn; 
} 
1
public static List<T> FindControlByType<T>(Control mainControl,bool getAllChild = false) where T :Control 
    { 
     List<T> lt = new List<T>(); 
     for (int i = 0; i < mainControl.Controls.Count; i++) 
     { 
      if (mainControl.Controls[i] is T) lt.Add((T)mainControl.Controls[i]); 
      if (getAllChild) lt.AddRange(FindControlByType<T>(mainControl.Controls[i], getAllChild)); 
     } 
     return lt; 
    } 
2

Вот еще один вариант, так как существующие, предоставленные из них были не совсем то, что я имел в виду. Этот метод, возможно, работает как метод расширения и исключает проверку типа корневого/родительского контейнера. Этот метод в основном «Получить все потомка управления типа Т» метод:

public static System.Collections.Generic.IEnumerable<T> ControlsOfType<T>(this System.Web.UI.Control control) where T: System.Web.UI.Control{ 
    foreach(System.Web.UI.Control childControl in control.Controls){ 
     if(childControl is T) yield return (T)childControl; 
     foreach(var furtherDescendantControl in childControl.ControlsOfType<T>()) yield return furtherDescendantControl; 
    } 
} 
Смежные вопросы