I have multiple pictureboxes and I need to load random images into them during runtime. So I thought it would be nice to have a collection of all pictureboxes and then assign images to them using a simple loop. But how should I do it? Or maybe are there any other better solutions to such problem?
9 Answers
Using a bit of LINQ:
foreach(var pb in this.Controls.OfType<PictureBox>()) { //do stuff } However, this will only take care of PictureBoxes in the main container.
3 Comments
You could use this method:
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; } Then you could do something like this:
foreach (var pictureBox in GetControlsOfType<PictureBox>(theForm)) { // ... } 14 Comments
root.Controls.OfType<T>, though.Control became an ambiguous reference between System.Web.UI and System.Windows.Forms. I could find ContainerControl only in the Forms namespace, not under Web. And ContainerControl wouldn't accept a Web.UI Control. Has anybody else ran into this issue? (I'll work around my problem for now, but really really want to use this simple and elegant answer.)Panel does not inherit from ContainerControl, I had to go one level up in the Winforms class hierarchy and use ScrollableControl in order to include panel. I'm not sure yet what other issues that this may cause. I may update to only support the containers that I'm looking for.If you're at least on .NET 3.5 then you have LINQ, which means that since ControlCollection implements IEnumerable you can just do:
var pictureBoxes = Controls.OfType<PictureBox>(); I use this generic recursive method:
The assumption of this method is that if the control is T than the method does not look in its children. If you need also to look to its children you can easily change it accordingly.
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; } Comments
A simple function, easy to understand, recursive, and it works calling it inside any form control:
private void findControlsOfType(Type type, Control.ControlCollection formControls, ref List<Control> controls) { foreach (Control control in formControls) { if (control.GetType() == type) controls.Add(control); if (control.Controls.Count > 0) findControlsOfType(type, control.Controls, ref controls); } } You can call it on multiple ways. To get the Buttons:
List<Control> buttons = new List<Control>(); findControlsOfType(typeof(Button), this.Controls, ref buttons); To get the Panels:
List<Control> panels = new List<Control>(); findControlsOfType(typeof(Panel), this.Controls, ref panels); etc.
1 Comment
Here's another version since the existing provided ones weren't quite what I had in mind. This one works as an extension method, optionally, and it excludes checking the root/parent container's type. This method is basically a "Get all descendent controls of type T" method:
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; } } Comments
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; } Comments
This to me is by far the easiest. In my application, I was trying to clear all the textboxes in a panel:
foreach (Control c in panel.Controls) { if (c.GetType().Name == "TextBox") { c.Text = ""; } } 1 Comment
Takes Control as container into account:
private static IEnumerable<T> GetControlsOfType<T>(this Control root) where T : Control { if (root is T t) yield return t; if (root is ContainerControl || root is Control) { var container = root as Control; foreach (Control c in container.Controls) foreach (var i in GetControlsOfType<T>(c)) yield return i; } }