Search code examples
linqienumerablecontrolcollection

Linq To Select All controls where DI contains some text from ControlCollection


Linq has always befuddled me. I am trying to extract all controls from an ASP.Net form page where the ID of the control contains a specific string. The control collection is hierarchical and I want to return any matching controls from all levels. Am I anywhere in the ballpark here? I could really use some help/education. The collection parameter is the collection of controls from the page and controlID is the text I am searching for.

    public static Control FindControlsByControlID(ControlCollection collection, string controlID)
    {
        IEnumerable<Control> controls = collection.Cast<Control>();
        IEnumerable<Control> matchedControls = controls
            .SelectMany(p => p.Controls.Cast<Control>()
                .SelectMany(c => c.Controls.Cast<Control>())
                .Where(d => d != null ? d.ID != null ? d.ID.Contains(controlID) : false : false))
            .Where(a => a != null ? a.ID != null ? a.ID.Contains(controlID) : false : false);

        ConcurrentQueue<Control> cq;
        if (matchedControls != null)
            cq = new ConcurrentQueue<Control>(matchedControls);
        else
            return null;
        ...

Thanks in advance!


Solution

  • Use an extension method to get all child controls:

    public static class ControlExt {
        public static IEnumerable<Control> AndSubControls(this Control aControl) {
            var work = new Queue<Control>();
            work.Enqueue(aControl);
            while (work.Count > 0) {
                var c = work.Dequeue();
                yield return c;
                foreach (var sc in c.Controls.Cast<Control>()) {
                    yield return sc;
                    if (sc.Controls.Count > 0)
                        work.Enqueue(sc);
                }
            }
        }
    }
    

    Now you can test all the subcontrols in your ControlCollection:

    IEnumerable<Control> matchedControls = controls.SelectMany(c => c.AndSubControls())
                                                   .Where(a => a != null && a.ID != null && a.ID.Contains(controlID));