Why can't I use findcontrol to dynamically locate a control that I can see in 'this'

I am trying to dynamically allocate information to a group of placeholders on an asp page that uses a Masterpage.

I have 6 placeholders named Placeholder1 to PlaceHolder6 and I want to add a usercontrol containing a table with a header text label, an image and a button in as many as are required depending on data driving it.

Then I want to customise each usercontrol's headerlabel text, image and button text depending on variables from the driving data.

My problem is that although in debug I can see this.placeholder1 etc, I can't seem to find them using findcontrol.

Here is the page :

<%@ Page Language="C#" MasterPageFile="~/Templates/SitePage.Master" AutoEventWireup="true"
    CodeBehind="SelectTemplate.aspx.cs" Inherits="MM.MailCampaign.Web.Campaign.SelectTemplate"
    Title="Step 2 | Select your template | zzz Touch" %>

<asp:Content ID="Content1" ContentPlaceHolderID="Header" runat="server">
    <asp:Label ID="HeadingLabel" CssClass="Header" Text="Create a Mailing" runat="server"></asp:Label>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    <table border="0" cellpadding="0" cellspacing="0" width="100%">
        <tr>
            <td colspan="2">
                &nbsp;
            </td>
        </tr>
        <tr>
            <td>
                <table border="0" cellpadding="0" cellspacing="0" class="TabsTemplate">
                    <tr>
                        <td width="6">
                        </td>
                        <td align="center">
                            <asp:HyperLink ID="SigLink" runat="server" CssClass="TabsLinkRed" Text="Touch Mail"
                                NavigateUrl="~/Campaign/SelectTemplate.aspx"></asp:HyperLink>
                        </td>
                        <td align="center">
                            &nbsp;<asp:Label ID="Emails" runat="server" CssClass="Disabled" Text="Touch emails (available soon)"></asp:Label>
                        </td>
                        <td align="center">
                            <asp:Label ID="TxT" runat="server" CssClass="Disabled" Text="Touch TXT (available soon)"></asp:Label>
                        </td>
                    </tr>
                </table>
                <table border="0" cellpadding="0" cellspacing="0" width="100%" class="OuterTable">
                    <tr>
                        <td>
                            &nbsp;
                        </td>
                    </tr>
                    <tr>
                        <td align="left">
                            <table border="0" cellpadding="0" cellspacing="0" width="100%">
                                <tr>
                                    <td style="padding-left: 10px">
                                        <asp:Label ID="SubHeadingLabel" CssClass="SubHeading" runat="server" Text="Select your template"></asp:Label>
                                    </td>
                                    <td align="right" style="padding-right: 10px" colspan="2">
                                        <asp:Label ID="MailingForLabel" runat="server" CssClass="TextBold"></asp:Label>
                                    </td>
                                    <td align="right" width="90px">
                                        <asp:Image ID="SelectedImage" runat="server" ImageUrl="~/images/SelectedTwo.jpg" />
                                    </td>
                                    <td width="10px">
                                        &nbsp;
                                    </td>
                                </tr>
                            </table>
                        </td>
                    </tr>
                    <tr>
                        <td style="padding: 10px 10px 10px 10px" valign="top">
                            <table border="0" cellpadding="0" cellspacing="0" width="100%">
                                <tr>
                                    <td>
                                        &nbsp;<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
                                    </td>
                                    <td width="10">
                                        &nbsp;
                                    </td>
                                    <td>
                                        &nbsp;<asp:PlaceHolder ID="PlaceHolder2" runat="server"></asp:PlaceHolder>
                                    </td>
                                    <td width="10">
                                        &nbsp;
                                    </td>
                                    <td>
                                        &nbsp;<asp:PlaceHolder ID="PlaceHolder3" runat="server"></asp:PlaceHolder>
                                    </td>
                                </tr>
                                <tr>
                                    <td colspan="5">
                                        <table width="100%">
                                            <tr>
                                                <td height="5px">
                                                </td>
                                            </tr>
                                        </table>
                                    </td>
                                </tr>
                                <tr>
                                    <td>
                                        &nbsp;<asp:PlaceHolder ID="PlaceHolder4" runat="server"></asp:PlaceHolder>
                                    </td>
                                    <td width="10">
                                        &nbsp;
                                    </td>
                                    <td>
                                        <asp:PlaceHolder ID="PlaceHolder5" runat="server"></asp:PlaceHolder>
                                    </td>
                                    <td width="10">
                                        &nbsp;
                                    </td>
                                    <td>
                                        &nbsp;<asp:PlaceHolder ID="PlaceHolder6" runat="server"></asp:PlaceHolder>
                                    </td>
                                </tr>
                                <tr>
                                    <td height="20px">
                                    </td>
                                </tr>
                                <tr>
                                    <td align="left">
                                        <asp:Button ID="BackButton" runat="server" CssClass="RedButtonSmall_Back" Height="24px"
                                            Text="Back" BackColor="Transparent" BorderColor="Transparent" BorderWidth="0px"
                                            Style="text-align: right; padding-right: 10px;" OnClick="BackButton_Click" />
                                    </td>
                                </tr>
                            </table>
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
</asp:Content>


Here is the Usercontrol:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="GroupTemplateControl.ascx.cs"
    Inherits="MM.MailCampaign.Web.Controls.GroupTemplateControl1" %>
<div>
    <table border="0" cellpadding="0" cellspacing="0" id="tabLetter" width="200px">
        <tr>
            <td class="TitleHeader" align="left">
                <asp:Label ID="Title" runat="server" Text="TitleText"></asp:Label>
            </td>
        </tr>
        k<tr>
            <td>
                <table cellpadding="10" cellspacing="0" class="InnerTable" width="100%">
                    <tr>
                        <td align="center" valign="top">
                            <asp:Image ID="image" runat="server" Width="120px" Height="160px" ImageUrl="~/images/createmailingNEW/AvailableSoon.jpg" />
                        </td>
                    </tr>
                    <tr>
                        <td align="center">
                            <asp:Button ID="SelectButton" runat="server" CssClass="Redbutton" Height="24px" Text="Select template"
                                BackColor="Transparent" BorderColor="Transparent" BorderWidth="0px" Style="text-align: left;
                                padding-left: 7px" />
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
</div>

Using this in the codebehind page_load to place the user controls ready for customising.

            for (int i = 0; i < 6; i++)
            {
               
               Control oControl = LoadControl("~/controls/GroupTemplateControl.ascx");
               Control ph = (Control)FindControl("Placeholder" + i.ToString());
// ph is null here - why?  If I stop here and inspect 'this' I can see placeholder1, placeholder2 etc.

 // alternatively, I tried the indirect route with
//  Control ph = (Control)FindControlRecursive(this,"Placeholder" + i.ToString());

               ph.Controls.Add(oControl);

            }

        public static Control FindControlRecursive(Control container, string name)
        {
            if ((container.ID != null) && (container.ID.Equals(name)))
                return container;

            foreach (Control ctrl in container.Controls)
            {
                Control foundCtrl = FindControlRecursive(ctrl, name);
                if (foundCtrl != null)
                    return foundCtrl;
            }
            return null;
        }


Cheers




mimpactAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

exceterCommented:
IDs of your Place Holders are CamelCase, that is, capital letters of words - PlaceHolder...
0
robastaCommented:
exceter is right, e.g.    

   Control ph = (Control)FindControl("Placeholder" + i.ToString())

Should be

     Control ph = (Control)FindControl("PlaceHolder" + i.ToString())
0
mimpactAuthor Commented:
Sorry - Typo in my example - It still returns Null using matching case
0
Why Diversity in Tech Matters

Kesha Williams, certified professional and software developer, explores the imbalance of diversity in the world of technology -- especially when it comes to hiring women. She showcases ways she's making a difference through the Colors of STEM program.

robastaCommented:
There are two things:

1. The casing (should be "PlaceHolder"

2. The loop should start on 1, currently, it starts on 0, therefor the first time it looks for PlaceHolder0 (and does not find it), also change 'less than' to 'less than Or Equal to' so that 6 is included.  

Change the loop :
 
for (int i = 0; i < 6; i++)

Open in new window

to start on 1, like so:  
for(int i = 1; i <= 6; i++)

Open in new window

0
mimpactAuthor Commented:
That's true (i shld start at 1 - should have fixed that before I uploaded the example - but I was getting pretty frustrated by then) - but anyway, when it gets to 1 it should still return a value - but it doesn't.
0
robastaCommented:
i used your HTML markup with the following code and it worked (added my literal control on all six placeholders):
protected void Page_Load(object sender, EventArgs e)
        {
              for (int i = 1; i <= 6; i++)
            {
                
               //Control oControl = LoadControl("~/controls/GroupTemplateControl.ascx");
               Control ph = (Control)FindControl("PlaceHolder" + i.ToString());
// ph is null here - why?  If I stop here and inspect 'this' I can see placeholder1, placeholder2 etc.

 // alternatively, I tried the indirect route with
//  Control ph = (Control)FindControlRecursive(this,"Placeholder" + i.ToString());

               //ph.Controls.Add(oControl);
                  Literal lit = new Literal();
                  lit.Text = "test 123";
               ph.Controls.Add(lit);

            }
        }

Open in new window

0
mimpactAuthor Commented:
Hmmm.
So it must be something to do with this system

Would the class declaration affect finding controls?
This is the declaration for this page's class

   public partial class SelectTemplate : DealershipPage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
          .....

0
robastaCommented:
my mistake, I initially used your code on a page without a Master page.

Since your page uses a master page, you first need to get the ContentPlaceHolder, then call FindControl on the ContentPlaceHolder like this:
for (int i = 1; i <= 6; i++)
            {
                ContentPlaceHolder BodyContentPlaceHolder = (ContentPlaceHolder)this.Page.Master.FindControl("ContentPlaceHolder1");
                //Control oControl = LoadControl("~/controls/GroupTemplateControl.ascx");
                Control ph = (Control)BodyContentPlaceHolder.FindControl("PlaceHolder" + i.ToString());
                // ph is null here - why?  If I stop here and inspect 'this' I can see placeholder1, placeholder2 etc.

                // alternatively, I tried the indirect route with
                //  Control ph = (Control)FindControlRecursive(this,"Placeholder" + i.ToString());

                //ph.Controls.Add(oControl);
                Literal lit = new Literal();
                lit.Text = "test 123";
                ph.Controls.Add(lit);

            }

Open in new window


0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
mimpactAuthor Commented:
you the MAN!
0
mimpactAuthor Commented:
My description obscured part of the information needed to provide the answer initially, but once that was clarified, the answer came fast and accurate.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.