FindControl in Custom ITemplate

1.3k views Asked by At

I have a custom UserControl which uses a simple ITemplate:

<asp:Panel runat="server" ID="pnlExpander" CssClass="expander">
    <asp:HyperLink runat="server" ID="lnkExpand" Text="More Options" NavigateUrl="#" CssClass="lnkExpand"/>
    <asp:Panel runat="server" ID="pnlContent" CssClass="expanderContent" style="display: none">
        <asp:PlaceHolder runat="server" ID="plcContent"/>
    </asp:Panel>
</asp:Panel>

The template is rendered with two simple properties:

public class Expander {
    private ITemplate _contentTemplate;
        public ITemplate ContentTemplate {
            get { return _contentTemplate; }
            set { _contentTemplate = value; }
    }
    protected override void OnPreRender(EventArgs e) {
            if (ContentTemplate != null) {
                ContentTemplate.InstantiateIn(plcContent);
            }
    }

Everything displays correctly, but I can't use FindControl within the template. I get a reference to my combobox from VS intellisense, but a compilation error that it's null whern I actually load the page.

To find the combobox in th the template, I'm using:

var cboFilterCriticality = AspNetUtils.FindControlRecursive(optionsExpander,"cboFilterCriticality") as DropDownList;

And the actual template looks like this on the page:

<l49:Expander runat="server" ID="optionsExpander">
    <ContentTemplate>
        ... other controls
            <asp:DropDownList ID="cboFilterCriticality" runat="server" ValidationGroup="filterGrid" DataTextField="Key" DataValueField="Value" />
    </ContentTemplate>
</l49:Expander>
2

There are 2 answers

0
Echilon On BEST ANSWER

I resolved this by changing the UserControl which used an ITemplate. For some reason, it was calling InstantiateIn in OnPreRender, which is clearly way too late to render anything to be picked up by Page_Load in the page - see the Page LifeCycle and UserControls (half way down). I moved InstantiateIn to OnInit in the UserControl, and the problem solved itself.

0
Siamand On

The Asp.net's WebForm page:

<asp:Panel runat="server" ID="pnlExpander" CssClass="expander">
    <asp:HyperLink runat="server" ID="lnkExpand" Text="More Options" NavigateUrl="#" CssClass="lnkExpand"/>
    <asp:Panel runat="server" ID="pnlContent" CssClass="expanderContent" style="display: none">
        <asp:PlaceHolder runat="server" ID="plcContent"/>
    </asp:Panel>
</asp:Panel>

define the Expander class as following:

public class Expander { 
    public ITemplate ContentTemplate {get ;set;}
    public HtmlGenericControl ContentTemplateContainer{get;set;}
    protected override void OnInit(EventArgs e) {
        this.ContentTemplateContainer = new HtmlGenericControl("div");
        if (ContentTemplate != null) {
            ContentTemplate.InstantiateIn(container);
        }
        plcContent.Controls.Add(container);

    }
}

in OnInit of Page:

public override void OnInit(EventArgs e){
    base.OnInit(e);
    ViewState["ContentTemplateContainerID"] =  ContentTemplateContainer.ClientID;
}

and finally in Javascript :

var containerID = ViewState("ContentTemplateContainerID");
var elID = $get(containerID)[0].id;
var expander = $find(elID);