?
Solved

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

Posted on 2011-03-15
10
Medium Priority
?
606 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
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 2000 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

What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

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:…
NetCrunch network monitor is a highly extensive platform for network monitoring and alert generation. In this video you'll see a live demo of NetCrunch with most notable features explained in a walk-through manner. You'll also get to know the philos…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…
Suggested Courses

752 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