Get All Controls of a Specific Type

Get all controls of a specific type

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.

How to get ALL child controls of a Windows Forms form of a specific type (Button/Textbox)?

Here's another option for you. I tested it by creating a sample application, I then put a GroupBox and a GroupBox inside the initial GroupBox. Inside the nested GroupBox I put 3 TextBox controls and a button. This is the code I used (even includes the recursion you were looking for)

public IEnumerable<Control> GetAll(Control control,Type type)
{
var controls = control.Controls.Cast<Control>();

return controls.SelectMany(ctrl => GetAll(ctrl,type))
.Concat(controls)
.Where(c => c.GetType() == type);
}

To test it in the form load event I wanted a count of all controls inside the initial GroupBox

private void Form1_Load(object sender, EventArgs e)
{
var c = GetAll(this,typeof(TextBox));
MessageBox.Show("Total Controls: " + c.Count());
}

And it returned the proper count each time, so I think this will work perfectly for what you're looking for :)

How to find a control of type in the entire controls chain?

You have to use recursion and step through the Controls property of your controls:

private IEnumerable<T> GetAllOfType<T>(Control rootControl)
{
return rootControl.Controls.OfType<T>().
Concat(rootControl.Controls.OfType<Control>().SelectMany(GetAllOfType<T>));

}

You can use this like:

var allOfTestInterface = GetAllOfType<ITestInterface(this);

It takes all controls with that interface that are directly contained by the root control (with your OfType<>() call) and then calls the method again for all controls contained by that control, thus recursing through all containers. SelectMany flattens this nested lists into one list.

get all controls of a type and change their properties

So I solved it! Jon Skeet was right. The Tab in the TabControl didn't contain the controls I was looking for because they were all in a GroupBox!
I searched for them in the GroupBox and there they were. The CheckBoxes where unchecked and everything worked perfectly as it should.

@Jon Thx for the "observing" tip. I let the program show me the available Controls in the Tab using a MessageBox and that is how I solved it. Thx also for the user who deleted his answer because he interduced me to the OfType<>() method.That really made the code look better:

foreach (var groupbox in ModuleTab.Controls.OfType<GroupBox>())
{
foreach (var item in groupbox.Controls.OfType<CheckedListBox>())
{
for (int i = 0; i < item.Items.Count; i++)
{
item.SetItemChecked(i, false);
}
}
}

Get All Web Controls of a Specific Type on a Page

Check my previous SO answer.

Basically, the idea is to wrap the recursion of iterating through the controls collection using :

private void GetControlList<T>(ControlCollection controlCollection, List<T> resultCollection)
where T : Control
{
foreach (Control control in controlCollection)
{
//if (control.GetType() == typeof(T))
if (control is T) // This is cleaner
resultCollection.Add((T)control);

if (control.HasControls())
GetControlList(control.Controls, resultCollection);
}
}

and to use it :

List<DropDownList> allControls = new List<DropDownList>();
GetControlList<DropDownList>(Page.Controls, allControls )
foreach (var childControl in allControls )
{
// call for all controls of the page
}

[Edited 11/26/2013]: here is a more elegant way to reach this goal. I wrote two extensions methods that can walk the control tree in both directions. The methods are written in a more Linq way as it produces an enumerable:

/// <summary>
/// Provide utilities methods related to <see cref="Control"/> objects
/// </summary>
public static class ControlUtilities
{
/// <summary>
/// Find the first ancestor of the selected control in the control tree
/// </summary>
/// <typeparam name="TControl">Type of the ancestor to look for</typeparam>
/// <param name="control">The control to look for its ancestors</param>
/// <returns>The first ancestor of the specified type, or null if no ancestor is found.</returns>
public static TControl FindAncestor<TControl>(this Control control) where TControl : Control
{
if (control == null) throw new ArgumentNullException("control");

Control parent = control;
do
{
parent = parent.Parent;
var candidate = parent as TControl;
if (candidate != null)
{
return candidate;
}
} while (parent != null);
return null;
}

/// <summary>
/// Finds all descendants of a certain type of the specified control.
/// </summary>
/// <typeparam name="TControl">The type of descendant controls to look for.</typeparam>
/// <param name="parent">The parent control where to look into.</param>
/// <returns>All corresponding descendants</returns>
public static IEnumerable<TControl> FindDescendants<TControl>(this Control parent) where TControl : Control
{
if (parent == null) throw new ArgumentNullException("control");

if (parent.HasControls())
{
foreach (Control childControl in parent.Controls)
{
var candidate = childControl as TControl;
if (candidate != null) yield return candidate;

foreach (var nextLevel in FindDescendants<TControl>(childControl))
{
yield return nextLevel;
}
}
}
}
}

Thanks to the this keyword, these methods are extensions methods and can simplify the code.

For example, to find all DropDownList in the page, you can simply call:

var allDropDowns = this.Page.FindControl<DropDownList>();

Because of the use of the yield keyword, and because Linq is smart enough to defer execution of the enumeration, you can call (for example):

var allDropDowns = this.Page.FindDescendants<DropDownList>();
var firstDropDownWithCustomClass = allDropDowns.First(
ddl=>ddl.CssClass == "customclass"
);

The enumeration will stop as soon as the predicate in the First method is satisfied. The whole control tree won't be walked.

Get all controls with names that start with specific string

You can use Linq's where method:

foreach (Label l in this.Controls.OfType<Label>().Where(l => l.Name.StartsWith("tafel_noemer_")))
{
l.Text = "bla bla";
}

Finding all controls of multiple types?

You can accomplish what you're trying to do by using the common base class Control:

IEnumerable<Control> controls = this.Controls
.Cast<Control>()
.Where(c => c is RadioButton || c is CheckBox || (c is TextBox && c.Name == "txtFoo"));

foreach (Control control in controls)
{
if (control is CheckBox)
// Do checkbox stuff
else if (control is RadioButton)
// DO radiobutton stuff
else if (control is TextBox)
// Do textbox stuff
}

Get all controls from composite for a specific control type

You could use the getComponents and the use the instanceOf keyword as shown here.

Component[] components = this.getComponents();
List<Component> buttons = new ArrayList<Component>();

for (Component component : components)
{
if (component instanceof JButton)
{
buttons.add(component);
}
}

how to check if a control of a certain type?

I think what you are after is || change it to ||...that is the logical or operator.

foreach (Control ctr in eItem.Controls)
{
if(ctr is Label || ctr is DropDownList)
{
ctr.Visible = false;
}
}

| = bitwise operator

|| = logical or operator

Based on your edit

It appears your controls are inside an updatepanel, if that is the case you want to loop for all controls within the updatepanel's content template container.

Here you go:

foreach (Control ctr in UpdatePanel1.ContentTemplateContainer.Controls)
{
// rest of code
if(ctr is Label || ctr is DropDownList)
{
ctr.Visible = false;
}
}


Related Topics



Leave a reply



Submit