Contact   •   Products   •   Search

Rick Strahl's Web Log

Wind, waves, code and everything in between...
ASP.NET • C# • HTML5 • JavaScript • AngularJs

ASP.NET 2.0 MasterPages and FindControl()


Argh. I'm going through an older application and replacing a somewhat complex scheme of user control templating with Master Pages today. For the most part this has been going real well until I hit a page that that relies on page inheritance where there's a common page base class that needs to have access to the controls on the page.

 

ASP.NET has never made this exactly easy, because the base class doesn't allow you access to the controls from the lower level as ASP.NET adds the properties higher up in the hierarchy. In the past I've been working around this by adding properties for the controls to the base class and then overriding these properties, but in ASP.NET 2.0 the control definitions are auto-generate with no chance to override the control definitions. The only workaround has been using FindControl() and dynamically retrieve the control definitions.

 

And this is where things get a bit tricky with MasterPages. The problem is that when you use MasterPages the page hierarchy drastically changes. Where a simple this.FindControl() used to give you a control instance you now have to drill into the container hierarchy pretty deeply just to get to the content container.

 

So in the past I might have done this in my C# base class:

 

protected Label lblError = null;

protected DataGrid dgItemList = null;

 

protected void AssignControls()

{

    this.lblError = this.FindControl("lblError") as Label;

    this.dgItemList = this.FindControl("dgItemList") as DataGrid;

}

 

you now have to drill into the containership with code like this:

 

protected void AssignControls()

{

    this.lblError = this.Master.FindControl("Content").FindControl("lblError") as Label;

    this.dgItemList = this.Master.FindControl("Content").FindControl("dgItemList") as DataGrid;

}

 

This isn't so bad, except when you're trying to figure out how to get to your controls <s>.

 

It really seems lame that Microsoft hasn't added a recursive FindControl() method to the Control class that drills into child containers. While this certainly isn't optimal in terms of performance it sure would make life a lot easier in a lot of situations, and this surely is one of them.

 

Not exactly rocket science to create a method that does this:

 

/// <summary>

/// Finds a Control recursively. Note finds the first match and exists

/// </summary>

/// <param name="ContainerCtl"></param>

/// <param name="IdToFind"></param>

/// <returns></returns>

public static Control FindControlRecursive(Control Root, string Id)

{

    if (Root.ID == Id)

        return Root;

 

    foreach (Control Ctl in Root.Controls)

    {

        Control FoundCtl = FindControlRecursive(Ctl, Id);

        if (FoundCtl != null)

            return FoundCtl;

    }

 

    return null;

}

 

with  this the code becomes:

 

/// <summary>

/// Assigns controls from the subclassed control to this instance so

/// we always can access the controls in our base class.

/// </summary>

protected void AssignControls()

{

this.lblError = wwWebUtils.FindControlRecursive(this.Master,"lblError") as Label;      

this.dgItemList = wwWebUtils.FindControlRecursive(this.Master, "dgItemList") as DataGrid;

}

 

Although this is easier, I suspect it's better to do the explicit thing if that option is available to you as it probably has better performance. Also I suspect Microsoft didn't include this sort of a function in ASP.NET natively because there's potential ambiguity here – there could be more than one control Id that matches a name.

Make Donation


Feedback for this Post

 
# re: ASP.NET 2.0 MasterPages and FindControl()
by scottgu April 09, 2006 @ 6:20am
Way back when we debated having a recursive FindControl method. One thing we worried about what the performance impact of people mis-using it -- since doing deep walks of the entire control tree lots of time can really slow things down if you don't know what you are doing.

Going back to your problem above, you should be able to just declare the control names as protected fields on your base class -- ASP.NET 2.0 wires these up just like V1.1 does (if a page has a base class and it has the controls already declared, then it doesn't re-generate them on any sub-class).

Hope this helps,

Scott
# re: ASP.NET 2.0 MasterPages and FindControl()
by Rick Strahl April 09, 2006 @ 1:33pm
Scott, thanks for the feedback...

As to using protected properties for the control in the base - that doesn't work. I think that works if the properties are defined in the partial class, but not with the base class.

I have:

ItemListBase.cs (controls defined)

which is then inherited by the ASPX.cs partial classes. In there I can see the controls defined in ItemListbase.cs - in code inside of ItemListBase - is null.

So the way I work around this now is that I have a method AssignControls() that goes out and does a bunch of FindControl calls to retrieve controls and explicitly assign them.

I'm not sure why this should be so - the controls are obviously visible in the partial class higher up in the class hierarchy, so I'm not sure why they shouldn't be visible in the base class. The only thing I can defer from this is that ASP.NET creates teh new properties with the 'new' keyword so they override the base controls.

# re: ASP.NET 2.0 MasterPages and FindControl()
by Scott Allen April 10, 2006 @ 7:09am
Rick:

Try using CodeFileBaseClass in your @ Page directive. This let's the ASP.NET code generator find those protected fields in your base class and wire them to the controls in the aspx.

I wish we didn't need to use this attribute, it feels messy.

# re: ASP.NET 2.0 MasterPages and FindControl()
by Rick Strahl April 10, 2006 @ 4:00pm
Aaargh. Thanks Scott. That does indeed work. I had no idea about this directive and yes: It seems odd that this should be required. I can see the possible need to explicitly have things not stored on the base class, but I'd think that'd be the exception to the rule not the other way around.

Still, all things considered this is cleaner than my use of a set of FindControl() calls.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Bill Swartz April 14, 2006 @ 6:40pm
Rick, I ended up having to use this in your MessageDisplay sample. I've embedded the MessageDisplay page in a MasterPage and as you might suspect the FindControl didn't work. Funny thing was when researching why it didn't work, Google pointed me to a solution written by the same guy who wrote the MessageDisplay example..

Thanks on both counts.
Bill
# re: ASP.NET 2.0 MasterPages and FindControl()
by Rick Strahl April 14, 2006 @ 6:50pm
Bill, the solution to MessageDisplay is the CodeFileBaseClass attribute - if you specify that you won't need FindControl or FindControlRecursive to get at the controls.

And yes, this was part of the reason that this actually came up <g>...
# re: ASP.NET 2.0 MasterPages and FindControl()
by Siva April 27, 2006 @ 4:37pm
Rick,
I have a dropdownlist inside the gridview as a template column defined as follows:
<asp:TemplateField HeaderText="Choose Location">
<ItemTemplate>
<asp:DropDownList ID="ddlChooseLoc" runat="server">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
I have the gridview inside of a master page- content hierarchy.
I have declared the CodeFileBaseClass in your @ Page directive; I have also declared a variable of the type dropdownlist in the base class.
When I try to access it from the partial class I am getting a null value for the dropdownlist variable.
I even tried to a FindControl on the dropdownlist still I am getting a null.
Any idea what I may be missing?
Thanks
-Siva
# re: ASP.NET 2.0 MasterPages and FindControl()
by Siva April 28, 2006 @ 9:38am
I fixed it by adding a line to check if it is a datarow and only then I am doing a FindControl.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Sam April 29, 2006 @ 7:09am
Thanks,

You saved me a lot of time with the FindControlRecursive advice.

Sam
# re: ASP.NET 2.0 MasterPages and FindControl()
by Sean Williams May 16, 2006 @ 6:27am
I have an issue with FIndControl that is driving me crazy. I have taken the old IssueTracker Startup Kit and modified it extensively for my owb use. It worked fine in 1.1, but on converting to 2.0 my FindControl isn't behaving as desired.

I've looked at every MSDN ocurrance of the method as well as trolled the various .NET sites but nothing seems to solve my issue.

Anyway, I have a dropdownlist set into a panel of a UserControl. That user control is set on the main page of the IssueDetails. I use findCOntrol to find the dropdownlist (and it does) but the value isn;t captured. Any ideas? I cannot believe that the difference between 1.1 and 2.0 is so great that this simple method now fails...

Sean~

PS: I like the recursive find... a great tool if you don;t want to dig into the debug windows to find the path explicitly...:)
# re: ASP.NET 2.0 MasterPages and FindControl()
by KSVN May 19, 2006 @ 9:47am
I have a similar issue.

I have a dropdown in the master page that I need to repopulate my child page when the dropdown posts back. I can not get the value of the dropdown in the child page. I tried the findcontrol but does not give me a result.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Drew June 27, 2006 @ 11:13pm
Hi Rick...

I have a similar issue, I have been setting up the master page main content placeholder as its own variable...like thus...

Dim main As ContentPlaceHolder = CType(Master.FindControl("MainContent"), ContentPlaceHolder)

Then all other findcontrols are just main.findcontrol("yourcontrol"). If you were to setup the main content placeholder for this.Master.FindControl("Content") in your example above as its own variable, would it make drilling down quicker and easier to code, as it dosnt have to go back to find the masterpage contentplaceholder control to any find childern...?
# re: ASP.NET 2.0 MasterPages and FindControl()
by Rick Strahl June 28, 2006 @ 12:09am
Drew,

That only solves part of the problem. If you have other containers inside the master container you still need to drill into that. So yes it's good to bypass a step if you know it's there, but ultimately you may still need to drill deeper to find controls.

It's always best to find controls at the right level. It's usually generic code that has to use FindControl() in the first place so in those cases you usually don't have any control over what's actually available.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Simon C July 02, 2006 @ 2:18pm
Rick,
This looks just what I am trying to resolve myself, but in VB. I have a Grid view (GridView1) contained in a master page and I am trying to store the value of the selected records key in a session control.
So I have set up
Dim MasterGridView As GridView = CType(Master.FindControl("GridView1"), GridView)
but I am still getting a System.NullReferenceException.
My Sub routine then contains NewText = MasterGridView.SelectedRow.Cells(0).Text
in order to try and store the records ID.
Any views on how this type of issue can be reolved?

# re: ASP.NET 2.0 MasterPages and FindControl()
by Rick Strahl July 02, 2006 @ 3:53pm

Check the page to make sure what your container ship is. If the grid sits inside of another container - a panel or even a div with runat=server your containership stack is blown and FindControl won't find the control.

One way to see the container ship is to print the UniqueID of the control to the Web form - that'll show the names in the chain.
# re: CodeFileBaseClass
by Rick Strahl July 02, 2006 @ 3:57pm
As a sidenote to K. Scott Allen's comment about CodeFileBaseClass - this directive only works with direct page inheritance. If you have two pages that derive from the same CodeBeside class, and both both a have CodeFile= pointing at the same .cs or .vb file then CodeFileBaseClass works fine.

However, if you define your base class one level higher in the class hierarchy (ie. Page -> MyPageBaseClass -> MyPage1 -> MyPage2) you can't use CodeFileBaseClass to point at MyPageBaseClass. This means any truly generic Page subclass that doesn't have a visual ASPX file associated with it won't be able to see the any controls defined higher up in the tree even if the properties are defined at the base level.

# re: ASP.NET 2.0 MasterPages and FindControl()
by elpako August 03, 2006 @ 2:13am
Before I start seeking something about FindControl problem I find the same solution. Like we see - great minds thinking alike

Best
# re: ASP.NET 2.0 MasterPages and FindControl()
by Milind Amin August 18, 2006 @ 12:25pm
Good One!!!

Great to know about it.

Keep it up.
# re: ASP.NET 2.0 MasterPages and FindControl() for dynamically created IDs
by Mick September 12, 2006 @ 4:23pm
Hello all, I'm new to ASP.NET 2.0, and .NET in general, but I think my problem has similar bearing on this topic.

I am using a repeater to display a collection list on a content page and am using a master page. As the data is being bound to the repeater I'm attempting to dynamically generate TextBox IDs so that I can later associate the contents of each TextBox with the collection list object it's data was populated from.
((TextBox)e.Item.FindControl("txtBox")).ID = "txt_" + tempObjectList.FiscalYear.ToString();

So if the contents of the TextBox changes, I can save it back to the liste object it is associated with.
I am however having quite a time trying to access the TextBox ID after its assigned.
For example, if I set the ID = "txtbox_01" and try to access it using a find control, it breaks and gives me an "Object reference not set to an instance of an object" error. When I look at the page source, the TextBox ID is set to id="ctl00_contentBody_txt_01".
When trying to perform some action on the data in the TextBox I try to access it as follows:
((TextBox)FindControl("txt_" + tempObject.FiscalYear.ToString())).Text

Any help would be greatly appreciated!

Thanks,
Mick
# re: ASP.NET 2.0 MasterPages and FindControl()
by Prakar September 28, 2006 @ 12:35pm
Nice piece of code. It solved my problem of 2 days.

I have a UserControl form and everything is done there. only thing I do in aspx page is to call usercontrol and pass parameters. all this worked fine till I was not using MasterPages. When I started using MP, I got error "Object not referenced..." in my code behind for aspx page. I'll do somemore testing but it seems working fine after I added recursive FindControl.

thanks bunch.
# ASP.NET Forums - Problem Findcontrol and Masterpage
by Web Forms September 28, 2006 @ 8:43pm
# ASP.NET Forums - FindControl
by Web Forms October 02, 2006 @ 8:15am
# どっとねっとふぁんBlog : GridViewからデータを追加する
by どっとねっとふぁんBlog October 05, 2006 @ 2:30am
# ASP.NET Forums - FindControl() doesn't work if page has MasterPage
by Master Pages, Themes and Navigation Controls October 05, 2006 @ 8:41am
# ASP.NET Forums - contentplaceholder - how to loop through form values ?
by Master Pages, Themes and Navigation Controls October 09, 2006 @ 9:50am
# ASP.NET Forums - Storing the Key from GridView
by Data Presentation Controls October 13, 2006 @ 1:06pm
# DotNetSlackers: ASP.NET 2.0 MasterPages and FindControl()
by DotNetSlackers Latest ASP.NET News October 26, 2006 @ 9:38am
# re: ASP.NET 2.0 MasterPages and FindControl()
by sj November 10, 2006 @ 9:14am
I've an issue accessing content page's control with the use of master page.

Here is the code snippet

1. This is the declaration in the master page (masterPage.master)
<asp:ContentPlaceHolder ID="contentID" runat="server">
</asp:ContentPlaceHolder>


2.This is the declaration in the content page (content.aspx)
<asp:Content ID="contentID" runat="Server" ContentPlaceHolderID="contentDetails">
<asp:Label ID="Label1" runat="server" Text="Fisrt Text"></asp:Label>
</asp:Content>

3. Onpageload I'm trying to change the value of Label1 to "Second Text"
I have written the below code to do so but it is doing nothing. When the page loads I see "First Text", where in I'm expecting "Second Text"


Here are the couple of approach I took
1. Find control method

In conent.aspx.cs on Page_Load event I have the below code.

ContentPlaceHolder cnt;
cnt= (ContentPlaceHolder) Page.Master.FindControl("contentDetails");

Label lbl;
lbl= (Label) FindControlRecursive(this.Master, "Label1");
lbl.Text = "Second Text";


2. I Tried setting <%@ MasterType VirtualPath="~/masterPage.master" %>
but no luck..

3. I tried FindControlRecursive()
still it doesn't work

Anyone has any idea what is going wrong here??

thanks in advance.
-sj
# ASP.NET Forums - DropDownList based on data Control inside another Control
by Data Access and ObjectDataSource Control November 28, 2006 @ 1:20am
# re: ASP.NET 2.0 MasterPages and FindControl()
by steve November 29, 2006 @ 10:05am
I'm stuck on a problem which may be in a similar area, but I think don't have as much as 0.1% of Rick's know how, and I'm struggling!

I've written code to make my content page modify my master page, no problem, but now I'm looking at trying to place a version of this code as a method in the masterpage codebehind. My thinking was that this way I wouldn't have to add the code to all of the content pages. Codebehind in the content pages could simply call the relevant method. My problem was that I couldn't get masterpage codebehind to affect controls on the masterpage - I tried various permutations of FindControl, but I couldn't get it to work - "Object reference not set to an instance of an object".

I'd have thought that referencing a control on the masterpage from the masterpage codebehind would be easier, but I haven't been able to do it...

Any thoughts welcome, apologies if this is something of newbie query.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Rick Strahl November 29, 2006 @ 12:24pm
Well as this entry mentions FindControl() only finds controls at the current level of containership, so maybe you're not pointing at the right parent control to use FindControl? Using FindControlRecursive() should do the trick though if you start Page as the Root control.
# ASP.NET Forums - MasterPage with PlaceHolder containing a Formview and iteration
by Data Presentation Controls December 08, 2006 @ 6:18am
# re: ASP.NET 2.0 MasterPages and FindControl()
by Daniel December 19, 2006 @ 5:23am
hehe...so many people with the same problem.

Instead of iterating through the controls and do recurvise methods on the hierachy, try using the event called ItemDataBound. ItemDataBound is available on all of the Grid's (Repeater, GridView, DataGrid, etc)

The ItemDataBound gives you the ItemEventArgs for the control you are using.

I have an repeater which is placed inisde a MasterPage, in the repeater i have several Label control. So how do I find these Labels ?

Look here:

protected void rptTemplates_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Header || e.Item.ItemType == ListItemType.Footer)
{
foreach (Control ctrl in e.Item.Controls)
{
//Got ya...
}
}
}

Inside the foreach I have my labels...
# ASP.NET Forums - FindControl() problem
by Web Forms January 16, 2007 @ 5:42am
# djeeg blog: CodeFileBaseClass to the rescue of Page Inheritance
by djeeg blog January 17, 2007 @ 8:23am
# re: ASP.NET 2.0 MasterPages and FindControl()
by Daniel January 19, 2007 @ 6:50am
I am having a problem. I have my control inside an UpdatePanel>MultiView1>View1>asp:table and I can't find it.

I am generating some usercontrols (A) inside another usercontrol (B) and calling usercontrol (B) in an .aspx page that has a masterpage.

So, my aspx page calls the master page, and inside the container of the masterpage I call my usercontrol B. This usercontrol generates dynamically usercontrols of type A inside an asp:table. The asp:table is inside a View1, and the View1 is inside a Multiview1, and the Multiview1 is inside an Update Panel.

This is my html code (I should mention that control A has a checkbox, and 2 dropdownlists:

//This is usercontrol B and I register usercontrol A in this page
<%@ Register ... src="~/usercontrol_A.ascx" ... %>

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
 <ContentTemplate>
  <asp:MultiView ID="MultiView1" runat="server">
   <asp:View ID="View1" runat="server">
     <asp:Table runat="server" ID="offeredMenusTable" Width="720px"></asp:Table>
   </asp:View>
  </asp:MultiView>
 </ContentTemplate>         
</asp:UpdatePanel>


//This is the codebehind for this page:

//This creates the controls just find
private void create()
{
 TableRow trItem = new TableRow();//New <tr>
 TableCell tdItem = new TableCell();//New <td>
 TableCell tdItem2 = new TableCell();//New <td>
 
for(int i=0; i < 5; i++)
 {
   ns.ucs.uc_A.uc_A ckBox = (ns.ucs.uc_A.uc_A)LoadControl(@"~/ns/ucs/uc_/.uc_A.ascx");
   ckBox.ID = menuItemID.ToString() + "|" + i;

   tdItem.Controls.Add(ckBox);
   trItem.Cells.Add(tdItem);
   this.offeredMenusTable.Rows.Add(trItem);
   //this.offeredMenusTable.Controls.Add(trItem); I tried this, but no luck finding it either

  _arrlstFoodItemIDs.Add(ckBox.ID);//Adding the ckBox IDs to an ArrayList
 }
  Session["_arrlstFoodItemIDs"] = _arrlstFoodItemIDs;
}


//But when I try to find them the FindControl returns null

void checkAll()
{
  _arrlstFoodItemIDs = (ArrayList)Session["_arrlstFoodItemIDs"];
   
 for (int i = 0; i < _arrlstFoodItemIDs.Count; i++)
 {
   ns.ucs.uc_A.uc_A ckBox = (ns.ucs.uc_A.uc_A)LoadControl(@"~/ns/ucs/uc_/.uc_A.ascx");
   ckBox=this.FindControl(_arrlstFoodItemIDs[i].ToString()) as ns.ucs.uc_A.uc_A;
   
    //The line above returns null 

    if(ckBox._CbBoolVal == false)//_CbBoolVal-checks the usercontrol A checkbox
   {
     ckBox._CbBoolVal  = true;
   }
  }
}

//As I said before I generate the usercontrols (A) fine, but I can't find them. I've been working on this problem for 3 days now. So, any help is appreciated. Thank you!!!
# PreviousPage к MasterPage
by ASP.NET | Обсуждения @ GotDotNet.ru February 14, 2007 @ 2:21am
# ASP.NET Forums - Server Control dynamic access
by Web Forms February 21, 2007 @ 12:11am
# Glengamoi - Control.ClientID falsch
by Web Forms March 01, 2007 @ 7:47am
# re: ASP.NET 2.0 MasterPages and FindControl()
by dan m March 02, 2007 @ 1:18am
did you fix your problem djeeg blog ? I have a similar issue with a control that cant be resolved with the recurursive function - its a multiview within a formview template..

cheers, dan
# re: ASP.NET 2.0 MasterPages and FindControl()
by Bill B March 12, 2007 @ 1:52pm
This code will locate a linkbutton and a user control on a master page.
The below code is in the load event of the content page.
Usercontrol is a generic type.

Dim headerlnk As LinkButton
Dim menuCtl As UserControl
menuCtl = CType(Master.FindControl("SiteMapCtl1"), UserControl)
menuCtl.Visible = False
headerlnk = CType(Master.FindControl("lnkUnits"), LinkButton)
headerlnk.Visible = True
# re: ASP.NET 2.0 MasterPages and FindControl()
by Joshua Beall March 16, 2007 @ 6:28am
I've done a tiny bit of benchmarking on recursive FindControl calls, and I'm satisfied that it will be fast enough for me. On my dev workstation (single core P4 running at 3.6GHz, 2 gigs of RAM), .NET could do a recursive control lookup through a page with 115 controls lightning fast. I got only 0ms results. I added System.Threading.Thread.Sleep(75) just to make sure that my timing code was correct (it was).

Keep in mind that many systems (mine included) don't have a timer resolution of less than about 16ms. See here:
http://www.eggheadcafe.com/articles/20021111.asp
So the fact that I am always getting 0ms results really means that it is finishing in less than 16ms. Still blazing fast, in my opinion.

But don't take my word for it; try timing it yourself. But I'm satisfied that a recursive control lookup will work fine for my purposes. I've override the Page.FindControl method with a recursive lookup for my MasterPage-enabled apps.

-Josh
# re: ASP.NET 2.0 MasterPages and FindControl()
by Rick Strahl March 16, 2007 @ 2:38pm
Joshua a single call to FindControlRecursive isn't going to kill you, but many calls will probably become noticable especially on large forms and especially if a control is deep in the stack or not found at all. For occasional calls when you need to drill down it's no problem at all, but if you're a control developer who's looking at every control on the page it would be a problem.

I think Scott's point of why they didn't put it in the product makes some sense although I still would love to see an optional parameter on FindControl to do the recursive lookup, rather than having a separate function. OTOH, I suspect anything we write on our end ourselves is likely to be faster than what Microsoft writes for us since they check for every possible failure/security scenario etc. <s> which is as it should be...
# re: ASP.NET 2.0 MasterPages and FindControl()
by Joshua Beall March 19, 2007 @ 1:55pm
You're probably right; it would become noticeable on large forms where there were lots of calls.

However, I'd still say, do some benchmarking before you say "it will work fine" or "it will be too slow." In my case I think it's going to work great. Let's say that it does add 12ms per lookup -- that means doing 5 lookups would cost me 60ms. Looking at the trace output for one of the forms I'm working on right now, i can see that total page generation time is about 900ms. That's about a 7% performance difference one way or the other. To me, that's acceptable. To others, maybe not.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Joshua Beall March 19, 2007 @ 1:58pm
That's a 7% performance difference, assuming that finding the control non-recursively incurse *no* performance hit at all; probably unrealistic. To find out the real performance difference, you'd have to try both methods and compare them.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Parimal April 04, 2007 @ 6:19pm
Hi,
How can i access the method wriiten in the Content Place Holder ASPX page from master page as the ASPX page gets loaded first than the Master Page load event?

Parimal
# re: ASP.NET 2.0 MasterPages and FindControl()
by Rick Strahl April 04, 2007 @ 6:53pm
You should never access content page content from a master page. If you have common code that needs to be accessible it should probably be contained in the master page.

You can always get access to the page through this.Page() in the master and then casting to your sepcific page type.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Parimal April 05, 2007 @ 12:10pm
Hi,

Thanks for the reply. I have a tab strip in Master Page and a Main ASPX page in COntent Place holder. We want to dynamically load the User Controls in the Panel in ASPX page when tab items are clicked. But the Problem is that ASPX page load event gets fired before Master Page events. SO ASPX page dont get what tab is clicked. So we want to access the ASPX page method for loading the USer control in the TAB click event of master page.

How to resolve these issue?

Thanks in Advance,

Parimal
# ASP.NET Forums - Control Visibility
by Getting Started April 26, 2007 @ 5:42am
# re: ASP.NET 2.0 MasterPages and FindControl()
by Alfred Ruffner April 26, 2007 @ 8:39pm
This technique actually made my eveining ..... Thanks
# Problem Findcontrol and Masterpage - ASP.NET Forums
by ASP.NET Forums May 19, 2007 @ 3:51am
# contentplaceholder - how to loop through form values ? - ASP.NET Forums
by ASP.NET Forums May 19, 2007 @ 11:46pm
# FindControl() doesn't work if page has MasterPage - ASP.NET Forums
by ASP.NET Forums May 21, 2007 @ 10:53am
# re: ASP.NET 2.0 MasterPages and FindControl()
by ben May 21, 2007 @ 11:02am
Thanks for this very good report!
I though, this is a bug, that the following code not work.
Control ctrl = this.FindControl("control");


thx ben
# FindControl() problem - ASP.NET Forums
by ASP.NET Forums May 29, 2007 @ 8:13am
# Server Control dynamic access - ASP.NET Forums
by ASP.NET Forums May 31, 2007 @ 7:00am
# MasterPage with PlaceHolder containing a Formview and iteration - ASP.NET Forums
by ASP.NET Forums June 06, 2007 @ 11:38pm
# Control.ClientID falsch - Glengamoi
by Glengamoi June 11, 2007 @ 2:31am
# Solution to the FindControl problem - ASP.NET Forums
by ASP.NET Forums June 16, 2007 @ 9:58am
# Storing the Key from GridView - ASP.NET Forums
by ASP.NET Forums June 17, 2007 @ 6:21pm
# FindControl - ASP.NET Forums
by ASP.NET Forums June 25, 2007 @ 3:01pm
# re: ASP.NET 2.0 MasterPages and FindControl()
by Arvind July 04, 2007 @ 3:59am
Another solution ...

Create a base class which inherits Page

Public Class DashBoardPage
Inherits System.Web.UI.Page

Then write a function in base class ....

Protected Overloads Function FindControl(ByVal id As String) As System.Web.UI.Control
Return Page.Master.FindControl("cphForm").FindControl(id)
End Function

Now use it in Partial class. (cphForm = Your main content area id on master page )
# どっとねっとふぁんBlog : コントロールを再帰的に発見する
by どっとねっとふぁんBlog July 06, 2007 @ 12:48am
# DropDownList based on data Control inside another Control - ASP.NET Forums
by ASP.NET Forums July 10, 2007 @ 3:56pm
# re: ASP.NET 2.0 MasterPages and FindControl()
by Robert MacLean July 22, 2007 @ 11:21am
You can do a cleaner containership drilldown by using the $ delimeter. Taking your first example it could become:
this.Master.FindControl("Content$lblError") as Label;
# re: ASP.NET 2.0 MasterPages and FindControl()
by Rick Strahl July 22, 2007 @ 11:56am
Robert you really shouldn't rely on the naming nor the containership like this. It works sure, but the naming is up to ASP.NET and that may change in the future. Also using the exact syntax above assumes you know the exact hierarchy of the controls down the control tree - if you know where the control lives exactly there would be no need to use FindControl in the first place. That'd be like doing FindControl(this.lblError.UniqueId) which is kinda non-sensical <s>.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Robert MacLean July 22, 2007 @ 12:53pm
I think you have missed what I have shown, the syntax is: <Master Page Content ID>$<Control ID>. It is no using the generated IDs (agreed those could change and thus shouldn't be used) but the ID you assign them at design time.

As for needing to recurse, the control can exist anywhere on the content page (even as a sub control), so the need to recurse is removed.

The only case where I could see you having an issue is if you have a master page within a master page, but since the designer doesn't support that I doubt anyone would hit that sort of issue).

To use your assign controls example. The only real change is the removing of the second FindControl :
protected void AssignControls()
{
    this.lblError = this.Master.FindControl("Content$lblError") as Label;
    this.dgItemList = this.Master.FindControl("Content$dgItemList") as DataGrid;
}
# re: ASP.NET 2.0 MasterPages and FindControl()
by Martin Blais August 06, 2007 @ 11:19am
Robert's solution work great for me and much easier to understand for me
# re: ASP.NET 2.0 MasterPages and FindControl()
by Rick Strahl August 06, 2007 @ 12:00pm
Robert - my point was that if you *know* the control path you can usually just reference the control directly or use FindControl on the appropriate container.

The recursive deal is useful in situations and required when you don't know the control path and you need to find a control. This is a common scenario in generic control development when one control interacts with others on the page.
# re: ASP.NET 2.0 MasterPages and FindControl()
by dotnetuncle August 20, 2007 @ 5:16am
Seems this method aint working when used to find a control within an update panel recursively.

Vishal Khanna
# re: ASP.NET 2.0 MasterPages and FindControl()
by navneet August 23, 2007 @ 3:16am
i am having problem while accessing dynamic control id of radio button.i am using master pages.with the help of findcontrol method i m doing bt 1 error came null value reference....please anybody help me.....thanx
# re: ASP.NET 2.0 MasterPages and FindControl()
by Eric September 21, 2007 @ 8:51am
This article helped with my issues using 'this.FindControl'.

Thanks.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Barry October 02, 2007 @ 1:30pm
This was a helpful article, as were the comments.

I have a similar setup where I have a hierarchy of classes in my pages. I have a base page class, a site page class, a forum page class, and a page type class. The base page class implements application logic. The site page class implements functionality unique to the site, as the application runs on several sites. The forum page class implements functionality specific to forums (areas), and the page type class implements specific page type functionality (Contact Us Page, Discussion Page, Chat Page, etc.)

I needed for the base page class to have access to several controls on the page, and I didn't want to make several calls to FindControl as I assumed the performance would be terrible. What I did was register control names in the Page.Init. Effectively, I built a collection/array of control names. Any of the page classes in the hierarchy could add to this array. Effectively, they were saying "I'm going to need access to control xyzzy. Please find it for me." Then, in the base page class's load method, I manually traversed the page's control tree. Each time I found a control name that matched one that had been registered, I added a reference in another collection to that control. MyPageControls("xyzzy") = Object. After this routine ran, each of the page classes could access the controls they needed via the collection.

I still wasn't overly fond of this, but it seemed much more efficient than calling Page.FindControl 30 or 40 times.

Eventually, I added a prefix to control names that needed to be identified. This way I was a little more efficient in the code. I could then say "If left(Control.ID,4)="XYZ_" then MyPageControls.Add(Control.ID,Control)". This seemed a bit more efficient since I didn't have to traverse/search a collection of control names for each control I found.

NOW, I find this! (Thank you Google for bringing this page up when I searched on "asp.net findcontrol performance".)

It seems that performance would benefit from using the "CodeFileBaseClass" directive.

Thanks! (And I hope I didn't miss something by not reading all of the posts!)
# re: ASP.NET 2.0 MasterPages and FindControl()
by Barry October 02, 2007 @ 1:57pm
I called it...

Rick Strahl (7/2/06) pegged it. If you have a deeper page hierarchy, you're screwed on that whole CodeFileBaseClass solution.

Guess I'll stick with my existing solution.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Chris November 30, 2007 @ 1:11am
Hi, spent ages trying to get this to work. After reading the code above a second time I got this working perfectly. Thank you very much!
# re: ASP.NET 2.0 MasterPages and FindControl()
by Wyatt Wong December 12, 2007 @ 9:48pm
I am not sure whether Rick's code can be used to locate controls that are buried inside DataGrid, GridView, Repeater, etc. However, I found another resource on the Internet titled "In Search of ASP.Net Controls" which can be found in http://www.odetocode.com/articles/116.aspx

I recently got into a problem in finding a TextBox inside a Repeater control in a MasterPage environment and I finally got the solution with the following code:

this.Repeater1.DataSource = ds; // ds is some data source
this.Repeater1.DataBind(); // Bind the Repeater1 with the data source

// Locate the TextBox control in a MasterPage environment
// i is the row number where TextBox is located inside the Repeater

TextBox tb = this.Master.FindControl("ContentPlaceHolder1").FindControl("Repeater1").Controls[i].FindControl("MyTextBox") as TextBox;
# re: ASP.NET 2.0 MasterPages and FindControl()
by Brent VanDusen January 01, 2008 @ 12:10pm
Caught your presentation at Dev Connections in Vegas. Always good - I also read your blog on the airline trip to get there - lol (been there done that too). This article solved my problem quickly. I figured that the control was buried inside the master page container. I just needed the syntax- which you had. It reminds me of how you have to access child controls in a custom control.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Nicolette January 04, 2008 @ 1:42pm
Thank you <b>soo</b> much! I spent almost 2 days trying to find the solution to this.
I kept encountering this error: System.NullReferenceException "Object reference not set to an instance of an object". However, when I did a Watch I was able to see the previous page's controls (with their values), and that left me scratching my head.

<b>Here's my old code</b>
using System;
using System.Configuration;
using System.Collections;
using System.Data;
using System.IO;
using System.Security.AccessControl;
using System.Security.Permissions;
using System.Security.Principal;
using System.Security;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class PODResults : System.Web.UI.Page
{
private DatabaseManager DBM = new DatabaseManager();
protected DataTable resultDT = new DataTable();
private Int16 rowCt = 0;
private Int64 executionTime = 0;
private string criteria = "";

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
try
{
string pagename = "";
if (PreviousPage != null && PreviousPage.IsCrossPagePostBack)
{

pagename = PreviousPage.ToString();
criteria = ((TextBox)PreviousPage.FindControl("txtCriteria")).Text;
resultDT = DBM.PODiscrepancy(criteria);
resultDT.AcceptChanges();
rowCt = (Int16)resultDT.Rows.Count;

}


if (rowCt == 0)
{ /* Let user know that there were no results.
disable the buttons on the search results
*/
BtnExcel.Visible = false;
//BtnClr.Visible = false;
//msg_Lbl.Text = "No Records Found";
//msg_Lbl.ForeColor = System.Drawing.Color.Red;
} //end if


} //end try

catch (Exception ex)
{
Console.WriteLine("Application caught exception. Exception found at {0}", ex.StackTrace);
}
finally
{
Session["PODRequestEnd"] = System.DateTime.Now;
Session["PODExecutionTime"] = (System.DateTime.Now.Ticks - ((DateTime)Session["PODRequestStart"]).Ticks) / 600000000; //convert ticks to minutes 1 minute = 600,000,000 ticks

executionTime = (Int64)Session["PODExecutionTime"];
rowCt = (Int16)resultDT.Rows.Count;
if (rowCt > 0)
{
//Finally, I can begin to work with the data set.
Session["PODResultsDataTable"] = resultDT;
rptPODResults.DataSource = resultDT;
rptPODResults.DataBind();
OnExportGridToCSV();
//Response.Write("finally");
}
}//end finally

} //end if
else
{ // IsPostBack


//Finally, I can begin to work with the data set.
resultDT = (DataTable)Session["PODResultsDataTable"];
rowCt = (Int16)resultDT.Rows.Count;
rptPODResults.DataSource = resultDT;
rptPODResults.DataBind();
//Response.Write("finally");


}

return;


} //Page_Load()

public void BtnExcel_Click(object sender, System.EventArgs e)
{ //or I can use the same exact code that I used to create the CSV file and put a ".xls" extension on the filename.
try
{

if (rowCt > 0)
{
DataGrid myDataGrid = new DataGrid();
myDataGrid.DataSource = resultDT;
myDataGrid.DataBind();

Response.Clear();

Response.AddHeader("content-disposition", "attachment;filename=" + Convert.ToString(DateTime.Now.ToString()) + "_PODiscrepancyResults.xls");

Response.Charset = "";

Response.Cache.SetCacheability(HttpCacheability.NoCache);

Response.ContentType = "application/vnd.ms-excel";

System.IO.StringWriter stringWrite = new System.IO.StringWriter();

System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);

myDataGrid.Controls.Clear();

myDataGrid.RenderControl(htmlWrite);//Tell the datagrid to render itself to our htmltextwriter

Response.Write(stringWrite);

//Response.End();
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
else
Response.Write("Error not caught: Zero Rows To Display!");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Response.Write(ex.Message);
}

return;

}//BtnExcel

private void OnExportGridToCSV()
{


//string currentUser = WindowsIdentity.GetCurrent().Name.ToString();

//DirectorySecurity ds = Directory.GetAccessControl(Server.MapPath("~/OutputFiles/"));

//AuthorizationRuleCollection arc = ds.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));

//string sas = WindowsIdentity.GetCurrent().Groups.ToString();
//string pUser = Page.User.Identity.Name;
//string wUser = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
//string currentPrincipal = System.Threading.Thread.CurrentPrincipal.Identity.Name;



try
{
if (rowCt > 0)
{
// Create the CSV file to which grid data will be exported.

string fileName = DateTime.Now.ToShortDateString() + "_PODiscrepancyResults.csv";
fileName = fileName.Replace("/", "");
string fileNameAndPath = Server.MapPath("~/OutputFiles/") + fileName;
//StreamWriter sw = new StreamWriter(Server.MapPath("~/OutputFiles/"+fileName), false);

int iColCount = resultDT.Columns.Count;
if (File.Exists(fileNameAndPath))
{
File.Delete(fileNameAndPath);
}
StreamWriter sw = File.CreateText(fileNameAndPath);

// First we will write the headers.

for (int i = 0; i < iColCount; i++)
{
// Can pick out the specific columns. Do not write all the data that's in the GRID.not useful to user
sw.Write(resultDT.Columns[i].ColumnName);
if (i < iColCount - 1)
{
sw.Write(",");
}
}
sw.Write(sw.NewLine);
// Now write all the rows.
foreach (DataRow dr in resultDT.Rows)
{

for (int i = 0; i < iColCount; i++)
{
//pick out the specific columns. Do not write all the data that's in the GRID.not useful to user
if (!Convert.IsDBNull(dr[i]))
{
sw.Write((string)dr[i]);
}
if (i < iColCount - 1)
{
sw.Write(",");
}
}
sw.Write(sw.NewLine);
}
sw.Close();




} // if (resultDT.Rows.Count > 0)
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}//end ExportGridToCSV

}





<div style="background-color:blue; width:100%;height:20px;"> &nbsp;</div>
<b>Here is my new code</b>
--------------------------------------------------------
using System;
using System.Configuration;
using System.Collections;
using System.Data;
using System.IO;
using System.Security.AccessControl;
using System.Security.Permissions;
using System.Security.Principal;
using System.Security;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class PODResults : System.Web.UI.Page
{
private DatabaseManager DBM = new DatabaseManager();
protected DataTable resultDT = new DataTable();
private Int16 rowCt = 0;
private Int64 executionTime = 0;
protected string criteria = "";

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
try
{
string pagename = "";
if (PreviousPage != null && PreviousPage.IsCrossPagePostBack)
{



criteria = ((TextBox)PreviousPage.Master.FindControl("content").FindControl("txtCriteria")).Text;

criteria = ((TextBox)PreviousPage.FindControl("txtCriteria")).Text;
resultDT = DBM.PODiscrepancy(criteria);
resultDT.AcceptChanges();
rowCt = (Int16)resultDT.Rows.Count;

}


if (rowCt == 0)
{ /* Let user know that there were no results.
disable the buttons on the search results
*/
BtnExcel.Visible = false;
//BtnClr.Visible = false;
//msg_Lbl.Text = "No Records Found";
//msg_Lbl.ForeColor = System.Drawing.Color.Red;
} //end if


} //end try

catch (Exception ex)
{
Console.WriteLine("Application caught exception. Exception found at {0}", ex.StackTrace);
}
finally
{
Session["PODRequestEnd"] = System.DateTime.Now;
Session["PODExecutionTime"] = (System.DateTime.Now.Ticks - ((DateTime)Session["PODRequestStart"]).Ticks) / 600000000; //convert ticks to minutes 1 minute = 600,000,000 ticks

executionTime = (Int64)Session["PODExecutionTime"];
rowCt = (Int16)resultDT.Rows.Count;
if (rowCt > 0)
{
//Finally, I can begin to work with the data set.
Session["PODResultsDataTable"] = resultDT;
rptPODResults.DataSource = resultDT;
rptPODResults.DataBind();
OnExportGridToCSV();
//Response.Write("finally");
}
}//end finally

} //end if
else
{ // IsPostBack


//Finally, I can begin to work with the data set.
resultDT = (DataTable)Session["PODResultsDataTable"];
rowCt = (Int16)resultDT.Rows.Count;
rptPODResults.DataSource = resultDT;
rptPODResults.DataBind();
//Response.Write("finally");


}

return;


} //Page_Load()

public void BtnExcel_Click(object sender, System.EventArgs e)
{ //or I can use the same exact code that I used to create the CSV file and put a ".xls" extension on the filename.
try
{

if (rowCt > 0)
{
DataGrid myDataGrid = new DataGrid();
myDataGrid.DataSource = resultDT;
myDataGrid.DataBind();

Response.Clear();

Response.AddHeader("content-disposition", "attachment;filename=" + Convert.ToString(DateTime.Now.ToString()) + "_PODiscrepancyResults.xls");

Response.Charset = "";

Response.Cache.SetCacheability(HttpCacheability.NoCache);

Response.ContentType = "application/vnd.ms-excel";

System.IO.StringWriter stringWrite = new System.IO.StringWriter();

System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);

myDataGrid.Controls.Clear();

myDataGrid.RenderControl(htmlWrite);//Tell the datagrid to render itself to our htmltextwriter

Response.Write(stringWrite);

//Response.End();
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
else
Response.Write("Error not caught: Zero Rows To Display!");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Response.Write(ex.Message);
}

return;

}//BtnExcel

private void OnExportGridToCSV()
{


//string currentUser = WindowsIdentity.GetCurrent().Name.ToString();

//DirectorySecurity ds = Directory.GetAccessControl(Server.MapPath("~/OutputFiles/"));

//AuthorizationRuleCollection arc = ds.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));

//string sas = WindowsIdentity.GetCurrent().Groups.ToString();
//string pUser = Page.User.Identity.Name;
//string wUser = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
//string currentPrincipal = System.Threading.Thread.CurrentPrincipal.Identity.Name;



try
{
if (rowCt > 0)
{
// Create the CSV file to which grid data will be exported.

string fileName = DateTime.Now.ToShortDateString() + "_PODiscrepancyResults.csv";
fileName = fileName.Replace("/", "");
string fileNameAndPath = Server.MapPath("~/OutputFiles/") + fileName;
//StreamWriter sw = new StreamWriter(Server.MapPath("~/OutputFiles/"+fileName), false);

int iColCount = resultDT.Columns.Count;
if (File.Exists(fileNameAndPath))
{
File.Delete(fileNameAndPath);
}
StreamWriter sw = File.CreateText(fileNameAndPath);

// First we will write the headers.

for (int i = 0; i < iColCount; i++)
{
// Can pick out the specific columns. Do not write all the data that's in the GRID.not useful to user
sw.Write(resultDT.Columns[i].ColumnName);
if (i < iColCount - 1)
{
sw.Write(",");
}
}
sw.Write(sw.NewLine);
// Now write all the rows.
foreach (DataRow dr in resultDT.Rows)
{

for (int i = 0; i < iColCount; i++)
{
//pick out the specific columns. Do not write all the data that's in the GRID.not useful to user
if (!Convert.IsDBNull(dr[i]))
{
sw.Write((string)dr[i]);
}
if (i < iColCount - 1)
{
sw.Write(",");
}
}
sw.Write(sw.NewLine);
}
sw.Close();




} // if (resultDT.Rows.Count > 0)
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}//end ExportGridToCSV

}
# re: ASP.NET 2.0 MasterPages and FindControl()
by Wyatt Wong January 13, 2008 @ 7:34pm
I would like to recursive Find ALL Controls instead of providing a particular control ID to find, how can I achieve this ?
# re: ASP.NET 2.0 MasterPages and FindControl()
by Mitja Fortuna January 24, 2008 @ 11:56pm
Thank you so much. I've been cracking my head for days with this problem.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Rudi Jensen February 06, 2008 @ 2:06am
So simple, but what a burden removed from my shoulders. THANK YOU
# re: ASP.NET 2.0 MasterPages and FindControl()
by Anuj Saxena February 08, 2008 @ 6:31am
sir ,
how to make the subdomain folder in web application by using asp.net and copy all files which are present in a particular domain.
Just example -->

www.ibloz.com website domain have some files and folder in wwwroot folder.I wanna to copy all files in this domain as a individual folder for a particular user.If a user name
is anuj then webite as a called by url www.anujibloz.com.
# re: ASP.NET 2.0 MasterPages and FindControl()
by David March 27, 2008 @ 7:34am
THanks - really useful to me after hours of trying!
# re: ASP.NET 2.0 MasterPages and FindControl()
by Danzig March 30, 2008 @ 8:18pm
Thanks Rick.

I'm still amazed by the amount of time that myself and other developers waste on finding answers to issues like this in order to achieve something incredibly simple. eg. I just want to get the text value submitted in a text box.

I thought that .Net was supposed to make developer's lives easier. With classic ASP we knew that we could get the value of any form element with request.form("element_name") and it worked regardless of any template etc design.

Classic ASP: request.form("element_name")
ASP.Net: this.lblError = this.Master.FindControl("Content").FindControl("element_name") as Label;


Progress? I think not.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Rick Strahl March 30, 2008 @ 11:06pm
@Danzig - you can still do all the things that ASP classic did. If you don't use features like Master Pages the whole naming container issue is rarely a problem and you can still do Request.Form["element_name"]. Of course you can always do: Request.Form[element_name.UniqueId] but then if you know the control I guess you wouldn't be in this place in the first place.

If you want simple - keep it simple. Don't use master pages, don't use the high level abstractions and you get the same behavior. if you want to take advantage of the high level features then you have to play by the rules of the framework.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Saber April 05, 2008 @ 8:36am
Thanks, It was what I were looking for!

GBN
# re: ASP.NET 2.0 MasterPages and FindControl()
by Frenky B. April 27, 2008 @ 11:20pm
Thanx Rick and God bless you.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Fat Boy May 13, 2008 @ 9:36pm
What about from a
Master -> PlaceHolder -> ControlHolder -> User control -> GridView.SelectedValue ---> NULL

the funny thing is that I can see the
GridView.SelectedValue
GridView.SelectedIndex
GridView.SelectedKey.Value

from the watch panel, everything has got the value

but.... it throws NULL Object.....

btw, i was trying to do some work at Pre-Render
# re: ASP.NET 2.0 MasterPages and FindControl()
by Momenee May 21, 2008 @ 8:02am
Below is a pseudo aspx page layout, not to be taken literally.

<Content>
<ListView>
<LayoutTemplate>
<DataPager />
</LayoutTemplate>
<ItemTemplate>
<TabContainer>
<TabPanel>
<Label ID="lblHx" Text='<%# Eval("Hx")%>' />
</TabPanel>
<TabPanel>
<Label ID="lblExam" Text='<%# Eval("Exam")%>' />
</TabPanel>
...
</TabContainer>
</ItemTemplate>
<EditItemTemplate>
<TabContainer>
<TabPanel>
<TextBox ID="txtHx" Text='<%# Bind("Hx")%>' />
</TabPanel>
<Tabpanel>
<TextBox ID="txtExam" Text='<%# Bind("Exam")%>' />
</TabPanel>
...
</TabContainer>
</ListView>
<ObjectDataSource />
</Content>

The object that is passed to my update method is not picking up the values entered by the user in the page's Web controls.

Do I need to handle the Updating event of ListView and there use your FindControlRecursive method to reference the controls inside the AJAXControlToolkit.Tabcontainer control to manually fill the object being passed to my update method?

For the sake of simplicity, the following omits any reference to the object being passed and shows how to get the text from a control inside one of the tabpanels using your method. My question is, Is this the only (or best) way to get the values I need for my object, which really defeats the idea of using an object at all since you need to manually set the value of each property?

protected void lvOpenVisits_ItemUpdating(object sender, ListViewUpdateEventArgs e)
{
ListView lv = sender as ListView;
TextBox hx = FindControlRecursive(lv, "txtHx") as TextBox;
string txt = hx.Text;
}
# re: ASP.NET 2.0 MasterPages and FindControl()
by Awadhesh May 27, 2008 @ 12:19am
i have a small problem, i am using the nested master pages in my asp.net application (using VS2008 Express Edition). I want to add dynamic menu in my master page, when i add this menu in single master page and bind through the database it is work fine,but when i try in the second level master page it is not work. please help me if you have any solution.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Jonas June 03, 2008 @ 12:10am
Thank you!

I used this.Page instead for a reference in my case though.

Again, thanks!

/Jonas
# re: ASP.NET 2.0 MasterPages and FindControl()
by Ghazanfar Khan June 27, 2008 @ 12:59pm
Hi Rick, great article. I was doing some research on quirks associated with masterpages when using FindControl in cross-page postbacks and after reading this and a few other articles, including ASP.Net 2.0 - Master Pages: Tips, Tricks, and Traps , by Scott, I'm begining to wonder if I should even dare :P

So I started tinkering with them in a test website. And surely, in a Page_Load of page that inherited from a master file, I could reference a control using a member variable like

Label lbl1 = lblName; //lblName exists on the aspx


but in the very next line,

Label lbl2 = (Label)Page.FindControl("lblName");
would not work.

Nor did

Label lbl3 = (Label)Page.FindControl("ctl00_ContentPlaceHolder1_lblName"); 
//ctl00_ContentPlaceHolder1_lblName being the clientID of the rendered Label ctrl


Also,

Content ct = (Content)Page.FindControl("Content1"); //did not yield anything


nor using


Page.Master.FindControl instead of Page.FindControl in any of the statements above was any good.

So, I'm wondering if the solution suggested by Scott Allen

(
Rick:

Try using CodeFileBaseClass in your @ Page directive. This let's the ASP.NET code generator find those protected fields in your base class and wire them to the controls in the aspx.

)
is a conclusive solution to this problem if we declare the control names as protected fields in the base class like he suggested.

Some others have suggested using the PreviousPageType directive on your page like
<%@ PreviousPageType VirtualPath="~/Page1.aspx" %>

and exposing what you need to access from the previous page as a public property.
In my application, I have several pages that can post to an "update.aspx" page, which then uses Page.PreviousPage.FindControl to find values in hidden fields from the previous page... Any suggestions on how I would do this if I used Masterpages...?

Incase Scott is reading this, I really enjoy your articles too. Whats your take on this?
How would you guys say I can recursively go through all the content controls on a page inheriting from a master page to just see all the controls, their parents and children just for experimentation sake...to see how the master and content pages are merged together?

Thanks again guys!

Ghazanfar
# re: ASP.NET 2.0 MasterPages and FindControl()
by Ghazanfar Khan June 27, 2008 @ 2:24pm
In reponse to my own post, I found that I can find the controls that are on the content page like this


protected void btnSubmit_Click(object sender, EventArgs e)
{

ContentPlaceHolder cph = (ContentPlaceHolder)Master.FindControl("ContentPlaceHolder1");
Label lbl0 = (Label)cph.FindControl("lblName");
TextBox txb1 = (TextBox)cph.FindControl("txbName");
DropDownList gen = (DropDownList)cph.FindControl("ddlGender");

lblResult.Text = lbl0.Text.ToString() + txb1.Text.ToString() + "<br>Gender: " +
gen.SelectedItem.ToString();

}

I realise that you (Rick or Scott) know this all too well, I thought I'd post for the benefit of other readers:)

Still, any suggestions on "how to think" to be able to percieve the hierarchy of the controls on the final rendered HTML..

I was also wondering, when a web request is sent to a server for a page that inherits from a master page, the server does the merge, generates the html and sends that to the clients browser, correct? Everytime this client posts back to the server, say, to do some operation on some user input on the same page, should it address the controls with their "new" IDs

eg. ConvertToInt32(ctl00_ContentPlaceHolder1_txb1.Text) +
ConvertToInt32(ctl00_ContentPlaceHolder1_txb2.Text);

or simply:

ConvertToInt32(txb1.Text) + ConvertToInt32(txb2.Text)

I realize we should never hardcode the ctl00_ContentPlaceHolder1_ part into our applications, but just wondering which of these two would be recognized? Still having a hard time grasping how the nuts & bolts of a masterpage driven page works...:(
# re: ASP.NET 2.0 MasterPages and FindControl()
by Cm.Shafi July 30, 2008 @ 12:51am
I have used following vbcode to load 5 textbox control dynamically
For i = 0 To j

Dim MyTextBox As New TextBox
MyTextBox.ID = "TextInBrief" & i
MyTextBox.TextMode = TextBoxMode.MultiLine
MyTextBox.Height = 88
MyTextBox.Width = 443
MyTextBox.Text = "TextInBrief" & i
Panel1.Controls.Add(MyTextBox)

Dim MyLiteral2 As New LiteralControl
MyLiteral2.Text = "<br/>"
Panel1.Controls.Add(MyLiteral2)
next

But when i try to retrieve the values of texboxes by clicking button1 got err:Object reference not set to an instance of an object. I have used masterpage.

button click code follows

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)handles Button1.Click

Dim brf As String = ""
Dim i As Int16 = 0
For i = 0 To 4
Dim txt As TextBox = CType(Master.FindControl("ContentPlaceHolder1").FindControl("TextInBrief" & i), TextBox)
If Trim(txt.Text) <> "" Then
brf = brf & txt.Text
End If
Next
label1.text=brf
end sub


the same code i used with other my project running perfectly.
But this i don't know.
Where i made mistake? Please help me.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Dejv August 01, 2008 @ 2:05am

Hello,
I used your function FindControlRecursive. :)
You saved my some time.

Bye
# re: ASP.NET 2.0 MasterPages and FindControl()
by Romi August 25, 2008 @ 1:29pm
Hi Rick,

Many Thanks, FindRecursive work wonderfull. I have one litle problem with one multi UC.
MasterPage(Uc1( Uc2))

FindRecursive works fine when I search Textboxes, Dropdowns in UC1 and UC2, but I not able to found one control selected inside one "Panel" used in one UC2

UC2 ( return one ItextControl --> textControl)
 <%@ Control Language="C#" AutoEventWireup="true" CodeFile="loc3_city.ascx.cs" Inherits="loc_city" %>
<asp:TextBox ID="LinkCity" runat="server" Visible="false" width="30px"></asp:TextBox>

<asp:ScriptManagerProxy ID="ScriptManagerProxy1" runat="server">
</asp:ScriptManagerProxy>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="conditional">
  <ContentTemplate>
    <asp:Panel ID="Panel1" runat="server"  Width="100px" Style="Display:inline">  </asp:Panel>
  </ContentTemplate>
</asp:UpdatePanel>
.

UC1
<li>
<com:MultiCombo ID="City" runat="server" />
</li>

UC1 inside MasterPage.

The UC2 return one Panel with the Cities to be selected. I can cast directly in UC1 when I use DrpdownBox and selected item, but Panel not cast!

This is the Html of the zone generated

<div id="ctl00_ContentPlaceHolder1_controlPanel_ctl00_ctl00_editMetaFields_ctl00_City_Panel1" style="width: 100px; display: inline;">
<div>
<select name="ctl00$ContentPlaceHolder1$controlPanel$ctl00$ctl00$editMetaFields$ctl00$City$ctl02">
<option value="1" selected="selected">NY</option>
<option value="2">LA</option>
</select>
</div>
</div>

Any sugestion?
# re: ASP.NET 2.0 MasterPages and FindControl()
by Thomas Hansen December 04, 2008 @ 9:44am
Here's a much better one; http://ra-ajax.org/jquery-ish-selector-for-webcontrols.blog

It's kind of like the jQuery Selector version for WebControls on the server ... ;)
# re: ASP.NET 2.0 MasterPages and FindControl()
by Fernando Paiva March 27, 2009 @ 2:34pm
Excellent ! It saved me some time trying to figure out how to access a control on my masterpage.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Chua Wen Ching May 07, 2009 @ 4:18am
Save me enormous time. Thanks :)
# re: ASP.NET 2.0 MasterPages and FindControl()
by Erik Pennings July 23, 2009 @ 2:10am
thanks
# re: ASP.NET 2.0 MasterPages and FindControl()
by LW August 09, 2009 @ 2:46pm
This is indeed a good help ! For about 2 days, I'm looking all answers and this finally solved my issue accessing from a Content page to a hyperlink visibility inside a LoginView of a Master page.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Ammar August 23, 2009 @ 11:01pm
This solution also works for getting to a control when the page has multiple master pages. I am just worried about efficiency of the solutions (its used about 2-3 times in a page load). However, with 4 master pages I fear that the code with FindControl may be hard to maintain/read in case that page structure does change? Have you come across this scenario before Rick? or what would be your recommended solution?
# re: ASP.NET 2.0 MasterPages and FindControl()
by sanjay October 07, 2009 @ 7:44pm
i love u rick
# re: ASP.NET 2.0 MasterPages and FindControl()
by Bob Avallone October 14, 2009 @ 7:43am
Thanks, Rick you're a lifesaver.
# re: ASP.NET 2.0 MasterPages and FindControl()
by jbeechii November 15, 2009 @ 12:12pm
Thanks, Rick - perfect for my needs!!
# re: ASP.NET 2.0 MasterPages and FindControl()
by kzen November 27, 2009 @ 1:00pm
Rick, just to say thanks, this saved me a ton of hair...
# re: ASP.NET 2.0 MasterPages and FindControl()
by Scott Hugh Alexandar Petersen November 30, 2009 @ 6:27am
Werks like a charm ;)

Thanks Rick
# re: ASP.NET 2.0 MasterPages and FindControl()
by Jan Blomquist January 23, 2010 @ 11:39am
The built-in FindControl in ASP.NET is recursive already. If you pass in a UniqueID, FindControl will traverse the control tree and find your control.

If you want to get it by traversing a child collection, simply throw in a simple LINQ extension method called All that will recursively decend any Control collection and you have yourself a neat selection mechanism:

For example:
MyPanel.Controls.All().OfType<Panel>().FirstOrDefault()
# re: ASP.NET 2.0 MasterPages and FindControl()
by Rick Strahl January 25, 2010 @ 11:20am
@Jan - if you pass in the uniqueId most likely you already have a control instance, so not sure that this is all that useful. The typical scenario is that you only have the 'local' control name and need to find that in a container and for that recursion is not native.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Jan Blomquist January 27, 2010 @ 4:41am
@Rick: In Ajax post/requests it's quite useful because you most likely have the full clientid/uniqueid.

I also pointed out this fact since very few (anybody?) has written anything about it. I myself discovered it while using Reflector.

Of course we agree that such a function is useful in some cases and that's why I provide the case that a useful LINQ extension is easier:

 public static IEnumerable<Control> All(this ControlCollection controls)
        {
            foreach (Control control in controls)
            {
                foreach (var grandchild in control.Controls.All())
                    yield return grandchild;
 
                yield return control;
            }
        }
# re: ASP.NET 2.0 MasterPages and FindControl()
by Ron February 24, 2010 @ 2:07pm
I have what I thought was a simple issue. I have a masterpage with a container. I want to get the values of the text boxes. Simple? No not for me. The textbox name is EventTitle. I tried

String ET = Request["EventTitle"].text; (All this does is give me the value that was originally there not what it was changed to)

<asp:TextBox ID="EventLink" runat="server"></asp:TextBox>

tried this in the code behind:

string EventTitle = Request["EventTitle"]; (using this I get a null)

I tried using the FindControl but that seems a bit comberson to get a value in the code behind. Every example I find is far different from eachother. I think there is something missing.

Any thoughts?
# re: ASP.NET 2.0 MasterPages and FindControl()
by Alex March 20, 2010 @ 3:24am
Thanks for the post AND many thanks to ScottGu for the tip about the "CodeFileBaseClass" @ page attribute, had no idea about it.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Charu Ramchandani April 12, 2010 @ 3:21am
Thanks a ton!!

Your blogs are really helpful. You saved me a lot of time.
Keep Writing!!! :)
# re: ASP.NET 2.0 MasterPages and FindControl()
by Baris May 17, 2010 @ 1:42pm
Wonderfulll
Thank you very much Rick. I've been looking this for hours.
And it works. Thanks again :)
# re: ASP.NET 2.0 MasterPages and FindControl()
by Raven June 02, 2010 @ 8:31am
Rick -

After banging my head against the wall (literally) for 3 days, I finally came across this post and IT WORKS!!!!

Thank you so much for sharing!
# re: ASP.NET 2.0 MasterPages and FindControl()
by raven June 02, 2010 @ 10:08am
I am running into some issues and I hope you or someone out there can help me. I am trying to loop thru all the items in a datalist. The datalist is located on a web user control page and that page is located in a wizard control step. here is some of the code. My issue is that when I loop through each item in my datalist: Genredropdownlist, PublicationLabelName, and PublicationLabelId return the same data for each item in the list. The count is 12 but it returns only data for 1. Please advise on how I can fix this matter. I looked at the id's for some of the Genredropdownlist controls and here are examples: ctl00_ContentPlaceHolder1_Wizard1_UserControl1_dlPubByGenre_ctl00_ddlAddGenre,
ctl00_ContentPlaceHolder1_Wizard1_UserControl1_dlPubByGenre_ctl01_ddlAddGenre,
ctl00_ContentPlaceHolder1_Wizard1_UserControl1_dlPubByGenre_ctl02_ddlAddGenre.

When I loop through the items it only returns data for this one: "ctl00_ContentPlaceHolder1_Wizard1_UserControl1_dlPubByGenre_ctl00_ddlAddGenre"

Please any help would be much appreciated.


pubgenredatalist = Me.UserControl1.FindControl("dlPubByGenre")
Dim count As Integer = pubgenredatalist.Items.Count
Dim i As Integer
Dim dlitem As DataListItem
Dim myTable As New DataTable
myTable.Columns.Add("Pub Id", Type.GetType("System.String"))
myTable.Columns.Add("Pub Name", Type.GetType("System.String"))
myTable.Columns.Add("Genre Id", Type.GetType("System.String"))
myTable.Columns.Add("Genre Name", Type.GetType("System.String"))


For Each dlitem In pubgenredatalist.Items
Dim Genredropdownlist As DropDownList = TryCast(wwWebUtils.FindControlRecursive(pubgenredatalist, "ddlAddGenre"), DropDownList)
Dim PublicationLabelId As Label = TryCast(wwWebUtils.FindControlRecursive(pubgenredatalist, "lblpubid"), Label)
Dim PublicationLabelName As Label = TryCast(wwWebUtils.FindControlRecursive(pubgenredatalist, "lblpubname"), Label)
Dim myrow As DataRow
myrow = myTable.NewRow
myrow("Pub Id") = CInt(PublicationLabelId.Text)
myrow("Pub Name") = PublicationLabelName.Text
myrow("Genre Id") = CInt(Genredropdownlist.SelectedValue)
myrow("Genre Name") = Genredropdownlist.SelectedItem.Text
Next
# re: ASP.NET 2.0 MasterPages and FindControl()
by James October 06, 2010 @ 8:29pm
Thanks for the example. I had to tweak it a bit to work when a given user control is used more than once on a page, but this was a good place to start from. Appreciate it.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Brent G November 19, 2010 @ 10:29am
I finally had it... I've decided to make this site my default site. For whatever reason I always seem to gravitate back to this site for solutions. Rick, you are the man!
# re: ASP.NET 2.0 MasterPages and FindControl()
by Brent G November 19, 2010 @ 10:29am
I finally had it... I've decided to make this site my default site. For whatever reason I always seem to gravitate back to this site for solutions. Rick, you are the man!
# re: ASP.NET 2.0 MasterPages and FindControl()
by novice January 16, 2011 @ 10:18pm
I have a master page MasterMain and a content page MyTest.
Inside the content page, MyTest, I have a text box control txtTestControl.
In the MyTest.aspx.cs, I am trying to assign a string value to the text property of the text box control.
Depending on what value is populated in the textbox, in the MyTest.aspx page, I am trying to
extract the value using the document.getElementByID().value in a java script function.

My problem is, if I hardcode the value in the Text Property of the textbox, I can extract it from MyTest.aspx page

But if I assign value like txtTestControl.Text = "abc" in the page load, it returns blank or null.

How do I assign value to the text property of a textbox control inside a content page?
# re: ASP.NET 2.0 MasterPages and FindControl()
by john January 20, 2011 @ 8:41am
Thanks for the info, I've been banging my head against the wall for this exact reason for a while now. It never occurred to me that the master page may be the issue. Thanks!
# re: ASP.NET 2.0 MasterPages and FindControl()
by Mark April 05, 2011 @ 9:48am
Rick, you are a guru - your solution just saved my bacon! Keep up the GREAT work!
# re: ASP.NET 2.0 MasterPages and FindControl()
by husain April 14, 2011 @ 3:12am
awesome Rick...you saved tons of my time and energy :)
Thanks a lot...and keep up the good work....
# re: ASP.NET 2.0 MasterPages and FindControl()
by Harvey Triana August 06, 2011 @ 9:02pm
Hello ... going to the initial question.

A good approach to solving the performance:

MasterPage:
...
<asp:ContentPlaceHolder id="cphMain" runat="server" />
...
Code of MasterPage:
...
public Control GetControl(string ID)
{
return cphMain.FindControl(ID);
}
....
A Page:
...
<%@ MasterType VirtualPath="~/MasterPage.master"%>
...
Code of Page:
...
this.lblError = Master.GetControl("lblError") as Label;
// insted of less performance
this.lblError = this.Master.FindControl("cphMain").FindControl("lblError") as Label;
# re: ASP.NET 2.0 MasterPages and FindControl()
by dotNetFollower September 29, 2011 @ 9:30pm
Nice article! My own FindControlRecursive helped me out many times, especially when I deal with MasterPages. For example, one of the usage of FindControlRecursive is shown in my post here - http://dotnetfollower.com/wordpress/2010/12/sharepoint-add-onchange-attribute-to-dropdownchoicefield/.
Thank you!
# re: ASP.NET 2.0 MasterPages and FindControl()
by Mark P February 25, 2012 @ 10:10am
After days of headaches trying to get a value of a specified field in a gridview row, I read through Scott's article http://www.asp.net/web-forms/tutorials/master-pages/control-id-naming-in-content-pages-cs which then led me to here. It appears Scott's resolution was exactly what i needed. (using the PageExtensionMethods). Before I found this I was getting the dreaded "object reference not set to an instance.." message. I'm somewhat of a Novice to Asp.Net and C# so I'm probably missing something obvious.

Summary: I am using a basically Masterpage / Content Page where I have a gridview bound to a sql table containing some rows of data firstname, lastname, state, etc. I enabled the option to delete, select, edit a row. Converted the CommandField to a TemplateFields.

When I click the Delete button for a specified row I am first firing RowDeleting method so I can grab the firstName value from the selected row and displaying the value to a label control.

protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
Label FirstName = (Label)Page.FindControlRecursive("Label1");
Label3.Text = FirstName.Text;
}

The correct record deletes but the FirstName Label from the RowDeleting method always returns the Firstname for the first record in the table. Why isn't (Label)Page.FindControlRecursive("Label1") retrieving the Firstname value for the row I clicked the delete button from?

During troubleshooting I set up this method

protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
Label FirstName = (Label)Page.FindControlRecursive("Label1");
Label2.Text = FirstName.Text;
}

Anytime I would click the Select button next to any row in my GV I would get the same result as above. (The FirstName) of the First Row.)

What am I missing or not understanding here?
# re: ASP.NET 2.0 MasterPages and FindControl()
by Ronen Festinger July 08, 2012 @ 9:19am
You can simply do now:
this.ContentPlaceHolderGridView.FindControl("GridViewManageList") as GridView;

instead of going to the master and search for the content, you can access it directly.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Nick May 18, 2013 @ 6:48pm
Scott Gu says: "One thing we worried about what the performance impact of people mis-using it -- since doing deep walks of the entire control tree lots of time can really slow things down if you don't know what you are doing. "

If anyone was really concerned about performance they wouldn't be using Webforms.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Rick Strahl May 18, 2013 @ 9:59pm
@Nick - that depends. WebForms is amongst the most optimized parts of ASP.NET. If you build tight WebForms (ie. little to no reliance on ViewState) those apps will run faster than MVC apps for example. Talking about slow tech, MVC uses so much dynamic and runtime reflection for inference of types etc. that it has quite a bit of overhead.

All in all the perf difference between the various ASP.NET platforms is relatively small either way though although I totally agree - if you use WebForms the way that most tutorials teach you and using massive third party controls you're quite likely to build a dog of an application. Same is true of other platforms though.

In short, don't spout unsubstantiated crap like that that is totally subjective and dependent on what you actually do in the specific application.
# re: ASP.NET 2.0 MasterPages and FindControl()
by Luis Damas May 23, 2013 @ 6:10pm
Public Shared Function FindControlRecursive(Root As Control, Id As String) As Control
  If Not (Root.ID Is Nothing) AndAlso Root.ID.ToUpper = Id.ToUpper Then Return Root

  For Each Ctl As Control In Root.Controls
  Dim FoundCtl As Control = FindControlRecursive(Ctl, Id)
  If Not (FoundCtl Is Nothing) Then Return FoundCtl
  Next
  Return Nothing
End Function
 


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2014