1
\$\begingroup\$

I have a function which loops over the controls on a form and checks to see if it's in a given rect, and then adds it or doesn't add it to a list<>. The parameter bContained is used to determine if we want a list of "in the rect" or "not in the rect" controls.

List<Control> getControls(Control container, Rectangle rect, bool bContained = false)
{
    List<Control> Selected = new List<Control>();

    rect = RectangleToClient(rect);

    foreach (Control ctl in container.Controls)
    {
        //Do we want selected or non-selected controls
        if (bContained)
        {
            if (rect.IntersectsWith(ctl.Bounds)) Selected.Add(ctl);
            foreach (Control ct in ctl.Controls) Selected.Add(ct);
        }
        else
        {
            if (!rect.IntersectsWith(ctl.Bounds)) Selected.Add(ctl);
            foreach (Control ct in ctl.Controls) Selected.Add(ct);
        }
    }

    return Selected;
}
\$\endgroup\$
0

2 Answers 2

1
\$\begingroup\$

You have an error there, unless you wanted to include all child controls regardless of whether they're contained. It should be:

if (rect.IntersectsWith(ctl.Bounds)) 
{    
    Selected.Add(ctl);
    foreach (Control ct in ctl.Controls) 
    {
        Selected.Add(ct);
    }
}

As for the test, instead of two cases you can use:

if(rect.IntersectsWith(ctl.Bounds) == bContained)
\$\endgroup\$
5
  • \$\begingroup\$ Says, "cannot convert from 'System.Windows.Forms.Control.ControlCollection' to 'System.Collections.Generic.IEnumerable<System.Windows.Forms.Control>" \$\endgroup\$ Commented May 31, 2018 at 0:23
  • \$\begingroup\$ Didn't realize that only implemented the non-generic IEnumerable. A foreach loop works, in that case. \$\endgroup\$
    – Errorsatz
    Commented May 31, 2018 at 0:28
  • \$\begingroup\$ and the test won't work, in this case. bContained determines if we want all the "contained" or "non-contained" controls. \$\endgroup\$ Commented May 31, 2018 at 0:30
  • \$\begingroup\$ Yes, so if bContained is true, you want rect.IntersectsWith to be true; if it's false, you want it to be false - in other words, to equal bContained. \$\endgroup\$
    – Errorsatz
    Commented May 31, 2018 at 0:31
  • \$\begingroup\$ My bad ... Looked at it wrong. You are correct. But, doesn't matter. Everybody, over at stackoverflow said my function was junk and the wrong way to do it. Told me to use LINQ. Haven't figured out, how to do that. Although, to me the foreach() on the list<>, seems the same to me as just doing a foreach like above. \$\endgroup\$ Commented May 31, 2018 at 1:07
2
\$\begingroup\$

You can make things more concise with LINQ. Here's one way that should work:

List<Control> getControls(Control container, Rectangle rect, bool bContained = false)
{
    rect = RectangleToClient(rect);
    return (from Control ctl in container.Controls
                  where rect.IntersectsWith(ctl.Bounds) == bContained                     
                  select new List<Control> { ctl }.Union(ctl.Controls.OfType<Control>()))
                  .SelectMany(x => x).ToList();
}

This basically does the same thing, filters the collection according to bContained. Creates a collection of lists that each contain the parent control and its sub-controls. Then flattens them into one list.

\$\endgroup\$
3
  • \$\begingroup\$ if, I wanted to change all my foreach statements to use LINQ, how could I change: foreach (Control c in controlSelection) { c.BackColor = Color.Fuchsia; } \$\endgroup\$ Commented May 31, 2018 at 3:33
  • \$\begingroup\$ @tobeypeters - If you need to transform each element you are probably better off staying with the foreach loop. If needed, there is a ForEach method in the LINQ extensions which will accomplish the same task.controlSelection.ForEach(x => x.BackColor = Color.Fuchsia); \$\endgroup\$
    – user33306
    Commented May 31, 2018 at 3:45
  • \$\begingroup\$ Ah ... This is. You sir, are very awesome. Thank you, for everything. I've meant to look into LINQ more and I will. \$\endgroup\$ Commented May 31, 2018 at 3:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.