views:

181

answers:

2

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.

+4  A: 

Hey,

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.

HTH.

Brian
I've updated my question, but I don't understand how to get the content to render there.
GenericTypeTea
OK, ideally, a custom control scenario is better for this, but you could try to override render and write it out here... ITemplate requires you to do the writing.
Brian
I don't think you understand. I want to create the controls in html like any other control. I've updated the question showing what I've acheived so far.
GenericTypeTea
Adding [TemplateInstance(TemplateInstance.Single)] can help so that you can directly reference controls within the template too... http://msdn.microsoft.com/en-us/library/system.web.ui.templateinstanceattribute.aspx. I'm not sure what I'm not understanding :-) you want to render the controls directly as a child of the user control, but want server-side access to it too, right?
Brian
+1 Thanks, I had tried that already (see my latest edit), but assumed it hadn't made a difference. I'll be accepting this answer though as you got in there first. Might be worth updating your answer so the comment that got you the points is obvious.
GenericTypeTea
Thank you. I updated it.
Brian
+1  A: 

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

VMAtm
No. I want it to work like the UpdatePanel. I don't want to have to search for everything using FindControl. The whole point of this Popup control is so it can be re-used and that it just encapsulates the controls that it will contain. The controls must still be accessible from the page.
GenericTypeTea
Then your problem is easy to solve, I've updated my answer
VMAtm
+1 Thanks, I had tried that already (see my latest edit), but assumed it hadn't made a difference. I'll be accepting Brian's answer though as he got in there first.
GenericTypeTea