1

I am dynamically creating a databound DropDownList control and adding it to placeholder in a databound Repeater control which is a custom user control placed on a page with tabs.

The Id of the DropDownList is set dynamically, and for the generated HTML below it is Comp1A

The control creation and usage works fine, but when I try to find the control recursively, I am always getting null.

Here is the generated HTML:

<select class="formDropDownRating" id="MainContent_ContentPlaceHolder1_TabContainer1_tab1_CE1_Repeater1_Comp1A_0" name="ctl00$ctl00$MainContent$ContentPlaceHolder1$TabContainer1$tab1$CE1$Repeater1$ctl00$Comp1A">
    <option value="5">5 - Strongly Agree</option>
    <option value="4">4 - Agree</option>
    <option value="3">3 - Somewhat Agree</option>
    <option value="2">2 - Disagree</option>
    <option value="1">1 - Strongly Disagree</option>

</select>

To find the control I am calling

target = FindDropDownListControl("Comp1A");

with

see Jeff Atwood's function

protected DropDownList FindDropDownListControl(string controlReference)
{
    Control root = this.Page.FindControl("ctl00"); //the Master page (the root control)
    var ddl = (DropDownList)MyApp.Utility.ExtensionMethods.FindControlRecursive(root, controlReference) as DropDownList; 
    return ddl;
}

Could anyone spot what could be the culprit? How can I get a reference to Comp1A?

Ash Machine
  • 9,601
  • 11
  • 45
  • 52

4 Answers4

1

I'm not 100% sure, because your code samples don't include how the controls are created, but if my suspicions are correct, the problem is that the control is being created at a point in the Page Lifecycle where it gets wiped out on the postback.

Where, exactly, is the control being created in the Page Lifecycle? If it's not being ccreated in the right place, or too late in the cycle, then it won't be preserved in the Viewstate on Postbacks.

If possible, ensure that it's being created in the Page_Init or else manually add it to Page_Init.

This article explains it more fully.

David
  • 72,686
  • 18
  • 132
  • 173
1

You should always try to use the container closest to the control as the root. If you can access the repeater or the repeater item, then use that as your root.

If you can't access the repeater, try using the page or the form as the root:

protected DropDownList FindDropDownListControl(string controlReference) 
{ 
    var ddl = (DropDownList)MyApp.Utility.ExtensionMethods.FindControlRecursive(Page, controlReference) as DropDownList;  
    return ddl; 
} 
James Johnson
  • 45,496
  • 8
  • 73
  • 110
0

I think it's look's something like that,

public static T FindControl<T>(this Control control) {
    T ctrl = default(T);
    if(control == null) return null;
    foreach(Control c in control.Controls) {
        if(ctrl == null) {
           ctrl = FindControl<T>(c);            
        }
        else return ctrl;
    }
}

I haven't tested it but you can match the example to your needs.

btw: you need to use it after PageLoad event if i remember correctly it's OnPreRender
than you will be able to see the result. Best Regards.

hackp0int
  • 4,052
  • 8
  • 59
  • 95
0

EDIT: My guess is that you have some other control within your page that also has the ID "Comp1A", and that your FindControlRecursive method is finding that control first. It's probably giving you null because that control, whatever it is, is not a DropDownList. When you do as DropDownList the result would be null in that case.

Here is what I know about FindControl, in case this is of any help to you.

FindControl is limited to controls within the same naming container (i.e. Parent/Ancestor control that implements the INamingContainer interface). If you are trying to find a control that is located inside of another control that is a naming container relative to the control on which you call the FindControl method, then it won't find it.

A Page is a naming container, as is a UserControl and a ContentPlaceHolder. I think that TabContainer is also a naming container, as well as each tab control within the TabContainer.

EDIT2: Repeater and RepeaterItem (each "row" of your repeater will be a RepeaterItem) are both naming containers as well. This means that you really can't reliably find a control that is nested within a repeater if you start looking from the top (i.e. the page). You need to set your starting point from within that same RepeaterItem (essentially this is what James Johnson suggested). If you need more help on this, then you will need to provide a little more information about the context where you are executing target = FindDropDownListControl("Comp1A");.

Your code is starting from the page and trying to dig down to find the "Comp1A" DropDownList. If this control were just a normal control within your "CE1" user control, then you could find it with something like the following:

this.Master.Master.FindControl("MainContent").FindControl("ContentPlaceHolder1").FindControl("TabContainer1").FindControl("tab1").FindControl("CE1").FindControl("Comp1A")

(Yikes! That's too long. See further below for shorter syntax.)

The master page also acts as a naming container, so that's why I started with this.Master instead of this.Page.

It looks like you are using a Master page within another Master page, therefore I've updated my example to use this.Master.Master.

According to Jeff's post, you can accomplish the same thing using the following syntax:

this.Master.Master.FindControl("MainContent:ContentPlaceHolder1:TabContainer1:tab1:CE1:Comp1A")

However, as mentioned above, the control you are trying to find is inside of a repeater. One thing you could do is iterate over all of the items in the repeater, like this:

Control repeater = this.Master.Master.FindControl("MainContent:ContentPlaceHolder1:TabContainer1:tab1:CE1:Repeater1");

foreach (Control control in repeater.Controls)
{
    var button = control.FindControl("Comp1A");
}

But if you are looking for one particular "Comp1A" DropDownList control from a particular row of the repeater, then you will need to utilize your context in order to use the correct root control for your search.

Dr. Wily's Apprentice
  • 10,212
  • 1
  • 25
  • 27