Solved

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

Posted on 2011-03-15
10
598 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
 
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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
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

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

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…
Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

746 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now