Get all objects of a certain type

  • Thread starter Magnus.Moraberg
  • 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.
 
J

Jon Skeet [C# MVP]

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
 
M

Magnus.Moraberg

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...
 
M

Magnus.Moraberg

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);
 
J

Jon Skeet [C# MVP]

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
 
M

Marc Gravell

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]
 
M

Magnus.Moraberg

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);
}
}
 
M

Marc Gravell

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top