Question

I've searched the site and I cannot find a solution for my problem, so apologies if it's already been answered (I'm sure someone must have asked this before).

I have written a jQuery Popup window that I've packaged up as a WebControl and IScriptControl. The last step is to be able to write the markup within the tags of my control. I've used the InnerProperty attribute a few times, but only for including lists of strongly typed classes.

Here's my property on the WebControl:

[PersistenceMode(PersistenceMode.InnerProperty)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public something??? Content
{
   get
   {
      if (_content == null)
      {
         _content = new something???();
      }
      return _content;
   }
}
private something??? _content;

Here's the HTML Markup of what I'm after:

   <ctr:WebPopup runat="server" ID="win_Test" Hidden="false" Width="100px" Height="100px"
      Modal="true" WindowCaption="Test Window" CssClass="window">
      <Content>
         <div style="display:none;">
            <asp:Button runat="server" ID="Button1" OnClick="Button1_Click" />
         </div>
         <%--Etc--%>
         <%--Etc--%>
      </Content>
   </ctr:WebPopup>

Unfortunately I don't know what type my Content property should be. I basically need to replicate the UpdatePanel's ContentTemplate.

EDIT: So the following allows a Template container to be automatically created, but no controls show up, what's wrong with what I'm doing?

[PersistenceMode(PersistenceMode.InnerProperty)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ITemplate Content
{
    get
    {
        return _content;
    }
    set
    {
        _content = value;
    }
}
private ITemplate _content;

EDIT2: Overriding the CreateChildControls allows the controls within the ITemplate to be rendered:

protected override void CreateChildControls()
{
   if (this.Content != null)
   {
      this.Controls.Clear();
      this.Content.InstantiateIn(this);
   }
   base.CreateChildControls();
}

Unfortunately I cannot now access the controls within the ITemplate from the codebehind file on the file. I.e. if I put a button within my mark as so:

<ctr:WebPopup runat="server" ID="win_StatusFilter">
   <Content>
      <asp:Button runat="server" ID="btn_Test" Text="Cannot access this from code behind?" />
   </Content>
</ctr:WebPopup>

I then cannot access btn_Test from the code behind:

protected void Page_Load(object sender, EventArgs e)
{
   btn_Test.Text = "btn_Test is not present in Intellisense and 
      is not accessible to the page. It does, however, render correctly.";
}

EDIT3: FIXED! Edit 2 is the correct soluion. It was just Visual Studios 2010 being a pain in the buttocks. Closed the app and reopened it and all my controls within the Content property were accessible on the page.

EDIT4: Edit 2 didn't fix the issue. I had already tried the [TemplateInstance(TemplateInstance.Single)] attribute before anyone had mentioned it, however at the time I didn't think it had made a difference. It appears Visual Studios 2010 is just being weird today.

Since I removed the tag and it carried on working, I assumed the attribute hadn't made a difference. Since going back to the code AGAIN the controls have become unavailable. Adding the attribute back in allowed it all to work and for the controls to be accessible server side. MADNESS. I will be accepting Brian's answer as he mentioned the fix before anyone else.

Was it helpful?

Solution

public ITemplate Content

which then you render to the UI like:

Label label = new Label();
this.Content.InstantiateIn(label);

//Render label

EDIT: Make sure the template also defines

[TemplateInstance(TemplateInstance.Single)]

as this allows you to access the controls within the template directly.

OTHER TIPS

You should try to use this:

win_StatusFilter.FindControl("btn_Test") // this will be a Control
win_StatusFilter.FindControl("btn_Test") as Button // this will be a Button if control found, otherwise it will be null.

Otherwise you should define some properties for your control, like in this article: http://msdn.microsoft.com/ru-ru/library/36574bf6%28v=VS.90%29.aspx


Update: According the remarks in this article about ContentTemplate property of the UpdatePanel:

http://msdn.microsoft.com/en-us/library/system.web.ui.updatepanel.contenttemplate(v=VS.90).aspx

you can get controls from ContentTemplate because of TemplateInstanceAttribute value (UpdatePanel.ContentTemplate has the TemplateInstance.Single).

So you should only use this code:

[PersistenceMode(PersistenceMode.InnerProperty)] 
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
[TemplateInstance(TemplateInstance.Single)]
public ITemplate Content

More information at:

http://msdn.microsoft.com/ru-ru/library/system.web.ui.templateinstanceattribute(v=VS.90).aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top