Thursday, February 24, 2011

ASP.NET: FindControl() returns null for an existing control while this control is still accessible via member variable

Building an AJAX enabled ASP.NET application we encountered the effect mentioned in the title of this article.

There is a TabContainer with a TabPanel containing a TextBox.

<cc1:TabPanel runat="server" ID="TabPanel1" TabIndex="0" HeaderText="Person">
<
ContentTemplate>
<asp:TextBox ID="TextBoxName" runat="server"></asp:TextBox>
</
ContentTemplate>
</
cc1:TabPanel>


This TextBox is accessible via a member variable, which is automatically created by Visual Studio Designer:


this.TextBoxName.Text = "Enter name here...";


If you try to access the TextBox using FindControl() method of Page class, you will be alerted with following message:



image



The error message is: “Object reference not set to an instance of an object.”.



That means, the FindControl() method cannot find the control by specified ID an returns null.



Slightly surprised (the TextBox is still accessible via member variable) we looked towards Microsoft Knowledge Base and Forums and found following article: http://msdn.microsoft.com/en-us/library/y81z8326%28v=vs.90%29.aspx#Y2166



It says: “When a control is not inside a naming container, you can get a reference to it by using the control's ID. When a control is inside a naming container, you must call a method that searches the naming container for the control's ID. A control might also be inside a naming container that you do not have direct access to.



To access a control by its ID inside a naming container, you have to extend your Page by instance method FindControlRecursive() described in the referenced article as well:

… 
((TextBox)this.FindControlRecursive(this,"TextBoxName")).Text = "Enter name here..."
… 
private Control FindControlRecursive(Control rootControl, string controlID) 

if (rootControl.ID == controlID) return rootControl; 
    foreach (Control controlToSearch in rootControl.Controls) 
    {


    Control controlToReturn =


                FindControlRecursive(controlToSearch, controlID);


     if (controlToReturn != null) return controlToReturn;


    }


    return null
}



It works! Enjoy…

2 comments:

dotNetFollower said...

Nice post! My own FindControlRecursive helped me out many times. Especially, when I deal with MasterPages. For example, one of such usage is shown in my post here – http://dotnetfollower.com/wordpress/2010/12/sharepoint-add-onchange-attribute-to-dropdownchoicefield/.
Thank you!

keeper54 said...

Excellent post. Exactly the solution I was looking for in trying find why my control couldn't be found. Good reference to the article; helped me understand exactly what was happening.