Solved

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

Posted on 2011-03-15
10
599 Views
Last Modified: 2013-12-17
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




0
Comment
Question by:mimpact
  • 5
  • 4
10 Comments
 
LVL 3

Expert Comment

by:exceter
ID: 35144826
IDs of your Place Holders are CamelCase, that is, capital letters of words - PlaceHolder...
0
 
LVL 14

Expert Comment

by:robasta
ID: 35144843
exceter is right, e.g.    

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

Should be

     Control ph = (Control)FindControl("PlaceHolder" + i.ToString())
0
 

Author Comment

by:mimpact
ID: 35144994
Sorry - Typo in my example - It still returns Null using matching case
0
DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

 
LVL 14

Expert Comment

by:robasta
ID: 35145085
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
 

Author Comment

by:mimpact
ID: 35145106
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
 
LVL 14

Expert Comment

by:robasta
ID: 35146299
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
 

Author Comment

by:mimpact
ID: 35146389
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
 
LVL 14

Accepted Solution

by:
robasta earned 500 total points
ID: 35146542
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
 

Author Comment

by:mimpact
ID: 35146582
you the MAN!
0
 

Author Closing Comment

by:mimpact
ID: 35146604
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

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

786 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question