Improving ASP.NET: Finding controls, Part 2
This is part of a series of posts offering ideas to improve ASP.NET.
I cringe when I see users would write recursive search code to find controls in the Page’s control tree. For example:
public void UpdateTextBoxCss(Control parentControl, string css)
{
foreach (Control child in parentControl.Controls)
{
if (child is TextBox)
((TextBox)child).CssClass = css;
else
UpdateTextBoxCss(child, css); // RECURSION
}
}
These control trees can be huge. Don’t forget that many controls that you add have their own child controls which also get searched (what a waste of CPU time!).
I would like to see a new event added to the Page class, OnControlAdded. Its called each time a control is added anywhere in the control tree. At the time this event handler is called, the control may not be fully prepared. Control properties still have to be assigned. So I would use this to create a collection of the exact controls I want to process. Then run through the collection at a later stage in the page cycle, such as in PreRender.
private List<TextBox> _TextBoxes = new List<TextBox>();
protected void Page_ControlAdded(object sender, EventArgs e) // sender is assumed to be the added control
{
if (sender is TextBox)
_TextBoxes.Add((TextBox)sender);
}
protected void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
foreach (TextBox textBox in _TextBoxes)
textBox.CssClass = "value";
}
From a third party control development standpoint, I have written controls that would use this. In the previous post, I described how FindControl is inefficient. When my control is looking for other controls of a specific type, it could search a much shorter list instead of using FindControl.
The truth is that the calls to Page_ControlAdded will have to process as many controls as the recursive search code shown earlier. But you only have a single search that collects controls into all lists once and the consumers of those lists will have much less to search. When my DateTextBox control is searching for a companion DateTextBox, I’m looking through a list reduced to just a few DateTextBoxes.
Does it need to be said that providing an OnControlRemoved event on Page is needed too?