Geeks With Blogs
The Quandary Phase This code was generated by a tool.

Here's a really short and simple bit of code that has the potential to be a bit of a time-saver.

The FindControl method of the Control class is used to find a specific child control of a given parent, searching by ID. This method, however, doesn't search the control hierarchy recursively: it searches the direct children of the specified parent control only.

While writing a recursive version of this method is trivial, a rather nice way to make the method reusable is to implement it as an extension method. Here's how it can be done:

namespace Boo.Web.UI.Extensions
{
    public static class ControlExtensions
    {
 
        /// <summary>
        /// recursively finds a child control of the specified parent.
        /// </summary>
        /// <param name="control"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public static Control FindControlRecursive(this Control control, string id)
        {
            if (control == null) return null;
 
            //try to find the control at the current level
            Control ctrl = control.FindControl(id);
 
            if (ctrl == null)
            {
                //search the children
                foreach (Control child in control.Controls)
                {
                    ctrl = FindControlRecursive(child, id);
                    if (ctrl != null) break;
                }
            }
 
            return ctrl;
        }
 
    }
}

And to call it:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using Boo.Web.UI.Extensions;
 
namespace MyWebApp
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        public void Page_Load(object sender, EventArgs e)
        {
            //call the recursive FindControl method
            Control ctrl = this.FindControlRecursive("my_control_id");
        }
    }
}

Don't forget to import the namespace within which the extensions method class is declared- or a compilation error will not long follow.

Now, all you need to do is import this same namespace for any pages/user controls/custom controls which need to use the recursive control search and you're good to go.

Doing it this way is of course logically no different to creating a static method in a util class, and passing both the parent control and the ID of the child control you want to find to it, but considering how commonly this functionality is required, it's nice to be able to tack it onto the control class itself, and extension methods provide an elegant way to accomplish this.

Posted on Wednesday, May 6, 2009 4:17 PM | Back to top


Comments on this post: ASP.NET: Recursive FindControl & Extension Methods

# re: ASP.NET: Recursive FindControl & Extension Methods
Requesting Gravatar...
There is an error in code resulting usually "stack overflow" (infinite recursive loop):

Now:
foreach (Control child in control.Controls)
{
ctrl = FindControlRecursive(control, id);
if (ctrl != null) break;
}

Should be:
foreach (Control child in control.Controls)
{
ctrl = FindControlRecursive(child, id);
if (ctrl != null) break;
}


or simply change ctrl = FindControlRecursive(control, id);
to ctrl = FindControlRecursive(child, id);
Left by Anonimowy Nieglosujacy on Jun 04, 2009 7:07 PM

# re: ASP.NET: Recursive FindControl & Extension Methods
Requesting Gravatar...
Yes, you're quite right- it should have been passing the child control, not the parent. I have updated it accordingly. Thanks! Adam
Left by adampooler on Jun 05, 2009 3:42 AM

# re: ASP.NET: Recursive FindControl & Extension Methods
Requesting Gravatar...
Your code works great. I've added a FindControlRecursiveFromTopLevel function that will automatically go to the page level from any control (also, it's in VB.Net for anyone interested in that):

Imports Microsoft.VisualBasic
Imports System.Runtime.CompilerServices

Namespace Extensions

Public Module WebControlExtensions

''' <summary>
''' Recursively loops through all containers in a control looking for the specified control.
''' </summary>
''' <param name="callingControl"></param>
''' <param name="controlId"></param>
''' <returns></returns>
''' <remarks></remarks>
<Extension()> _
Public Function FindControlRecursive(ByRef callingControl As System.Web.UI.Control, ByVal controlId As String) As System.Web.UI.Control

If callingControl Is Nothing Then Return Nothing

Dim ctrl As Control = callingControl.FindControl(controlId)

If ctrl Is Nothing Then
For Each child As Control In callingControl.Controls
ctrl = FindControlRecursive(child, controlId)
If ctrl IsNot Nothing Then Exit For
Next
End If

Return ctrl

End Function

''' <summary>
''' Recursively loops through all containers on the page that contains the control looking for the specified control.
''' </summary>
''' <param name="callingControl"></param>
''' <param name="controlId"></param>
''' <returns></returns>
''' <remarks></remarks>
<Extension()> _
Public Function FindControlRecursiveFromTopLevel(ByVal callingControl As System.Web.UI.Control, ByVal controlId As String) As System.Web.UI.Control
Dim ctrl As Control = FindControlRecursive(callingControl.Page, controlId)
Return ctrl
End Function

End Module

End Namespace
Left by Blake on Aug 07, 2009 12:43 PM

# re: ASP.NET: Recursive FindControl & Extension Methods
Requesting Gravatar...
Great idea, changed signature to create an overload like so, MyControl.FindControl(someId, true)

/// <summary>
/// Searches the current naming container for the specified server control.
/// </summary>
public static Control FindControl(this Control control, string id, bool recursive)
{
//call base implementation which only finds direct descendants
Control target = control.FindControl(id);

//do recursion?
if (recursive && target == null)
{
foreach (Control childControl in control.Controls)
{
target = childControl.FindControl(id, recursive);
if (target != null)
break;
}
}

return target;
}
Left by Elmar de Groot on Sep 13, 2009 10:20 AM

# re: ASP.NET: Recursive FindControl & Extension Methods
Requesting Gravatar...
Hi, I've written an alternative approach using a generic extension method to flatten the control hierarchy and then search the simple list afterwards. The code is here http://ulrikb.wordpress.com/2010/05/20/extension-method-to-flatten-any-recursive-collection/
Left by Ulrik B on May 20, 2010 1:47 AM

# re: ASP.NET: Recursive FindControl & Extension Methods
Requesting Gravatar...
I each time be a fan of this blog, I find it really well structured. Congratulations to the writer of the blog
Left by ugg adirondack tall on Nov 17, 2010 6:20 PM

# re: ASP.NET: Recursive FindControl & Extension Methods
Requesting Gravatar...

I found this is an informative and interesting post so i think so it is very useful and knowledgeable. I would like to thank you for the efforts you have made in writing this article. I am hoping the same best work from you in the future as well. In fact your creative writing ability has inspired me. Really the article is spreading its wings rapidly.
Indonesian Furniture | Indonesian Teak Furniture.
Left by Deddy Agoes on Dec 07, 2010 5:08 AM

# re: ASP.NET: Recursive FindControl & Extension Methods
Requesting Gravatar...
Listen, as usual in the subject. Thanks for the update, at the same time and read all over again - for good digestion of your thoughts.
Left by professional essay writing servi on Feb 15, 2011 7:25 AM

# re: ASP.NET: Recursive FindControl & Extension Methods
Requesting Gravatar...
You are best i really like your post keep it up
send flowers to australia
Left by jamed on Mar 02, 2011 5:42 PM

# re: ASP.NET: Recursive FindControl & Extension Methods
Requesting Gravatar...
great comments thank you for sharing usefull information
Left by mothers day flowers Argentina on Mar 26, 2011 12:11 AM

# re: ASP.NET: Recursive FindControl & Extension Methods
Requesting Gravatar...
Wanted to add that an Extender is used to add client functionality to an existing ASP.NET control, without the need to create a new server control.
Left by critique writing on Mar 27, 2011 1:46 AM

Comments have been closed on this topic.
Copyright © Adam Pooler | Powered by: GeeksWithBlogs.net | Join free