Get all objects of a certain type

  • Thread starter Thread starter Magnus.Moraberg
  • Start date Start date
M

Magnus.Moraberg

hi,

I have a form which contains a large number of datagridview objects.
At one point in my code, I need to validate all datagridviews except
the one I am working with. I'm actually validating a row in one
datagridview after I am sure that all other dgvs are valid. This is to
do with issues regarding child parent relationships between dgv.

What would really help me is if there was a way of filling an array
with references to all datagridviews within my form class. I could of
course have all datagridviews in an array but I'm actually using the
designer and it declares datagridviews as individual objects.

Any suggestions?

Barry.
 
I have a form which contains a large number of datagridview objects.
At one point in my code, I need to validate all datagridviews except
the one I am working with. I'm actually validating a row in one
datagridview after I am sure that all other dgvs are valid. This is to
do with issues regarding child parent relationships between dgv.

What would really help me is if there was a way of filling an array
with references to all datagridviews within my form class. I could of
course have all datagridviews in an array but I'm actually using the
designer and it declares datagridviews as individual objects.

Any suggestions?

This is a good example of the designer generating code which (contrary
to the name!) doesn't show good design.

I suggest you create the array (or list, preferably) *anyway* and
populate it within the constructor. You'll still have the other
variables around, unfortunately, but at least you'll still have the
list available.
Of course, you'll need to hand-edit the code every time you add a new
view...

Jon
 
This is a good example of the designer generating code which (contrary
to the name!) doesn't show good design.

I suggest you create the array (or list, preferably) *anyway* and
populate it within the constructor. You'll still have the other
variables around, unfortunately, but at least you'll still have the
list available.
Of course, you'll need to hand-edit the code every time you add a new
view...

Jon

Thanks for the reply
view...

That of course is my problem. What happens if I forget, or more
likely, those who inherit the code forget...
 
This is a good example of the designer generating code which (contrary
to the name!) doesn't show good design.

I suggest you create the array (or list, preferably) *anyway* and
populate it within the constructor. You'll still have the other
variables around, unfortunately, but at least you'll still have the
list available.
Of course, you'll need to hand-edit the code every time you add a new
view...

Jon

I guessing I can't do something along these lines in C# -

for(object obj in this.GetMyLocalVariables)
if(obj.ValueType == typeof(DataGridView)
dataGridViewList.append(obj);
 
I guessing I can't do something along these lines in C# -

for(object obj in this.GetMyLocalVariables)
  if(obj.ValueType == typeof(DataGridView)
    dataGridViewList.append(obj);

Not for local variables. You can do it for instance variables (using
typeof(Foo).GetFields) though... that may be good enough.
Or if they're added to the Controls collection, you could just iterate
through that.

Jon
 
I have similar requirements regularly - I just use a generic method to
recurse the Controls collection - something like:

class MyForm : Form
{
void SomeEvent(object sender, EventArgs args)
{
this.ApplyChildren<DataGridView>(dgv =>
{
// if not the current instance...
if (!ReferenceEquals(dgv, sender))
{
// ...validate this dgv
}
});
}
}

static void ApplyChildren<T>(this Control root, Action<T> action)
where T : Control
{
foreach (Control child in root.Controls)
{
ApplyChildren(child, action);
T typed = child as T;
if (typed != null) action(typed);
}
}

Marc
[C# MVP]
 
I have similar requirements regularly - I just use a generic method to
recurse the Controls collection - something like:

         class MyForm : Form
         {
             void SomeEvent(object sender, EventArgs args)
             {
                 this.ApplyChildren<DataGridView>(dgv =>
                 {
                     // if not the current instance....
                     if (!ReferenceEquals(dgv, sender))
                     {
                         // ...validate this dgv
                     }
                 });
             }
         }

         static void ApplyChildren<T>(this Control root, Action<T> action)
             where T : Control
         {
             foreach (Control child in root.Controls)
             {
                 ApplyChildren(child, action);
                 T typed = child as T;
                 if (typed != null) action(typed);
             }
         }

Marc
[C# MVP]

Thanks for your help. Heres what I've ended up doing -

public Form1()
{
InitializeComponent();

List<DataGridView> dataGridViews = new
List<DataGridView>();
List<Control> controls = new List<Control>();

GetControls(this, ref controls);

foreach(Control control in controls)
{
if (control.GetType() == typeof(DataGridView))
dataGridViews.Add((DataGridView)control);
}
this.dataGridViews = dataGridViews.ToArray();
}

void GetControls(Control parentControl, ref List<Control>
controls)
{
foreach (Control control in parentControl.Controls)
{
controls.Add(control);
GetControls(control, ref controls);
}
}
 
Note that the "ref" here does nothing - it would work just as well
without it ("ref" would be handy if GetControls said "controls = new
List<Control>()").

Marc
 
Back
Top