public static class ControlFinder{ /// <summary> /// Similar to Control.FindControl, but recurses through child controls. /// </summary> public static T FindControl<T>(Control startingControl, string id) where T : Control { T found = startingControl.FindControl(id) as T; if (found == null) { found = FindChildControl<T>(startingControl, id); } return found; } /// <summary> /// Similar to Control.FindControl, but recurses through child controls. /// Assumes that startingControl is NOT the control you are searching for. /// </summary> public static T FindChildControl<T>(Control startingControl, string id) where T : Control { T found = null; foreach (Control activeControl in startingControl.Controls) { found = activeControl as T; if (found == null || (string.Compare(id, found.ID, true) != 0)) { found = FindChildControl<T>(activeControl, id); } if (found != null) { break; } } return found; }}
In your base page, I suggest having these methods:
public T FindControl<T>(string id) where T : Control { // We know the control we're searching for isn't the Page itself, // so we use the more performant FindChildControl to search. return FindChildControl<T>(Page, id); } public T FindControl<T>(Control startingControl, string id) where T : Control { return ControlFinder.FindControl<T>(startingControl, id); } public T FindChildControl<T>(Control startingControl, string id) where T : Control { return ControlFinder.FindChildControl<T>(startingControl, id); }
There is a potential issue which I *think* could occur with Composite Controls which are not implemented according to guidelines or inherited from CompositeControl. This is related to the fact that EnsureChildControls() may not be called, and without a call to Control.FindControl, we've no way of forcing that to occur.
The result would most likely be null being returned when you might expect to have found a control. I suspect this issue could affect other dynamically created controls such as (the contents of) databound controls. This would only occur if you were searching for the id of one of the child controls contained by the composite / databound control.
If anyone has (or does) hit this issue, let me know, and if you work on the asp.net team or have had the time to 'reflector' through this scenario, I'd be grateful for clarification.
Great, I'm pleased its working out - I haven't actually got round to using it myself yet - I've still got some older code doing the job. Let me know if any issues come up.
DotnetNoobie - thx for the vb version, I formatted your comment a bit.