James Couvares
James Couvares

Reputation: 1783

Find all ASP.NET controls matching a predicate?

I need to enumerate over a collection of controls - regardless of their nesting level - that match a given predicate.

Originally the problem occurred, when I needed to set all textbox's in a grids row to ReadOnly, if a column in that row indicated that the record should not be editable.

Later I realized, that I already solved a problem in the past very much like this one, only with a different criteria (find a single control recursively by its ID).

After trying a few alternatives I came up with a general solution that works. But since I will use this method very often, I wanted to gather possible improvements.

This method will return all child controls matching a predicate:

public static IEnumerable<T> FindChildControls<T>(this Control parentControl,
    Predicate<Control> predicate) where T : Control
    {
        foreach (Control item in parentControl.Controls) {
            if (predicate(item))
                yield return (T)item;

            foreach (T child in item.FindChildControls<T>(predicate)) {
                yield return child;
            }
        }
    }

Using this method I can do the following:

var allTxt = Page.FindChildControls<TextBox>(c => c is TextBox);
var submit = Page.FindChildControls<Button>(c => c.ID == "btnSubmit").First();

Upvotes: 1

Views: 1361

Answers (1)

K.A.D.
K.A.D.

Reputation: 3718

You can use a queue to get rid of recursion if you want.

        public static IEnumerable<T> FindChildControls<T>(Control parentControl,
        Predicate<Control> predicate) where T : Control
        {
            Queue<Control> q = new Queue<Control>();

            foreach (Control item in parentControl.Controls)
            {
                q.Enqueue(item);
            }

            while (q.Count > 0)
            {
                Control item = q.Dequeue();
                if (predicate(item))
                    yield return (T)item;

                foreach (Control child in item.Controls)
                {
                    q.Enqueue(child);
                }
            }

        }

Upvotes: 5

Related Questions