internal class ControlFinder where T : Control
{
private readonly List _foundControls = new List();
public List FoundControls
{
get { return _foundControls; }
}
public List FindControls(Control control)
{
foreach (Control childControl in control.Controls)
{
if (childControl.GetType() == typeof(T))
_foundControls.Add((T)childControl);
else
FindControls(childControl);
}
return FoundControls;
}
}
It can be consumed like this:
var textboxes = new ControlFinder().FindControls(control);
This is exactly what I needed, but I found a need to be more fluid, and allow passing in the type rather than just using "TextBox". In my case, if the input controls needed to be disabled, I have this method:
It can be consumed like this:
var textboxes = new ControlFinder
This is exactly what I needed, but I found a need to be more fluid, and allow passing in the type rather than just using "TextBox". In my case, if the input controls needed to be disabled, I have this method:
public static void DisableTextBoxes(this Control control)
{
var controls = new ControlFinder().FindControls(control);
foreach (var textbox in controls)
{
textbox.Text = "";
textbox.Enabled = false;
}
}
As I said, this works great. But I'd like to write an extension method that allows passing in the type when called. The relevant code would be changed to this:
As I said, this works great. But I'd like to write an extension method that allows passing in the type when called. The relevant code would be changed to this:
public static void DisableTextBoxes(this Control control, Type type)
{
var controls = new ControlFinder().FindControls(control);
Problem is, this doesn't work. I get an error stating that the type or namespace couldn't be found. Is it not possible to initialize a generic class with a variable?
Problem is, this doesn't work. I get an error stating that the type or namespace couldn't be found. Is it not possible to initialize a generic class with a variable?
VulpesPosted Jul 17, 2014, 7:52 PM
To answer your original question, because of the way that generics work, the compiler needs to know what the type parameter actually is when creating a closed generic class and so you can't use a variable for this - you have to use the name of an actual type.
William SnellPosted Jul 17, 2014, 4:47 PM
My ControlFinder class recursively searches any Control passed to it to find child Controls of the specified type. This call correctly returns all TextBox Controls in the control passed in:
var textboxes = new ControlFinder
Also, I need the type to be known prior to attempting operations on the collection of controls found. I can't access the Text and Enabled properties of Controls without specifying their type. The DisableTextBoxes method I posted works because the type is specified when I create a new instance of ControlFinder.
What I wanted to accomplish was almost exactly what I already have, but instead the call to consume the FindControls method would look like this:
// Where 'type' is a type of Control passed in.
var controls = new ControlFinder
Actually, now that I'm thinking about it, I don't believe this is a good idea. I'd still have to cast to the required type to operate on, unless I'm missing something, which negates the benefit of not specifying the type when calling FindControls. I might be trying to refactor this too much.
VulpesPosted Jul 17, 2014, 4:29 PM
foreach (var c in controls)
If 'cc' is a reference to some container control and you're interested in disabling TextBoxes within that container, you could then call with:
cc.DisableControls