onefootswill
onefootswill

Reputation: 4079

FindControl and INamingContainer

I want to word this question carefully, so helpful people don't jump in and spend their time telling me information that I already know (I don't want to waste their time).

I want to understand how FindControl works in ASP.NET web application projects (the ones where the c# files are referenced as CodeBehind, NOT CodeFile, in the markup).

Code behind have two files which sit between the markup file. E.g. Default.aspx will have Default.aspx.cs and Default.aspx.designer.cs

If you put a button on a page, it is added to the designer file. For example: protected global::System.Web.UI.WebControls.LinkButton LinkButton1;

If you want to get a reference to that control, it is immediately available as a member of the Default class. E.g. this.LinkButton1.Text = "Click Me";

If you look at a trace for the page, it is given a unique id as per the behaviour for INamingContainers (here, the Page): ctl00$ContentPlaceHolder1$LinkButton1

The thing I don't understand is why a null is returned by the statement: Control c = Page.FindControl("LinkButton1");

I realise this is unnecessary, as the button is already available to the Default class. And this is because it appears as a member in the Default.aspx.designer.cs file.

The thing I do not understand is why null is returned. Because the Page implements INamingContainer, and the button has an ID which correlates to that expected of a control in an INamingContainer. Isn't this exactly the kind of thing FindControl finds?

Upvotes: 1

Views: 1330

Answers (3)

Joshua Ginn
Joshua Ginn

Reputation: 119

If you put it in a Panel, you can call

myPanel.FindControl("LinkButton1");

Upvotes: 0

Tim Schmelter
Tim Schmelter

Reputation: 460028

This behaviour was new to me, maybe because i wouldn't try to search for a control that is directly accessible anyway. I think this might also be the reason why ASP.NET not even allow this, because it's faster and safer to use an existing reference than to find it (or not).

The FindControl method can be used to access a control whose ID is not available at design time. The method searches only the page's immediate, or top-level, container; it does not recursively search for controls in naming containers contained on the page. To access controls in a subordinate naming container, call the FindControl method of that container.

http://msdn.microsoft.com/en-us/library/31hxzsdw.aspx

Edit: After i checked this behaviour, i've noticed that null is only returned if used on a Page with MasterPage, since the only control in the page's ControlCollection is the MasterPage itself. That makes sense. You cannot guarantee an ID to be unique when the control is on the top level of a page with MasterPage, because other ContentPages might as well have a control with this ID and FindControl could today return another control than tomorrow.

If you look at the NamingContainer of the Control you want to find, you see that in case of a MasterPage it is the ContentPlaceHolder and in case of a "normal" Page it is the Page itself.

So you need to get a reference to the MasterPage's ContentPlaceholder first before you could find the control via FindControl:

Page.Master.FindControl("ContentPlaceHolder1").FindControl("LinkButton1");

http://msdn.microsoft.com/en-us/library/xxwa0ff0.aspx

Upvotes: 3

Simon Mourier
Simon Mourier

Reputation: 138776

FindControl is not recursive, and it looks like you have an intermediary ContentPlaceHolder1 control, which is a naming container, so this should work: Page.FindControl("ContentPlaceHolder1").FindControl("LinkButton1")

Upvotes: 3

Related Questions