Content is not allowed between the opening and closing tags for user control

I found this:

ASP.Net: User control with content area, it's clearly possible but I need some details

Works like a charm, but I wish I could suppress the design time message, content is not allowed between opening and closing tags, but it works at run time.

[ParseChildren(true, "Content")]

[PersistChildren(false)]

public partial class CollapsiblePanelControl : UserControl

{

    private Control content;

    // add the content
    this.MainContent.Controls.Add(content);

    // if this is not a post back
    if (!this.IsPostBack)
    {
        // set to true;
        this.Expanded = true;
    }
}

The markup is like this:

<asp:Panel ID="CollapsiblePanelMainPanel" runat="server" CssClass="collapsiblepanel">
    <asp:Panel ID="CollapsibleHeaderPanel" runat="server" CssClass="collapsibleheaderpanel">
        <asp:ImageButton ID="CollapseButton" ImageUrl="~/Images/BlueArrowDown.png" runat="server" OnClick="ExpandButton_Click" CssClass="expandbutton" /> 
        <asp:Label ID="CollapsiblePanelHeaderLabel" runat="server" Text="Collapsed" CssClass="collapsiblelabel"></asp:Label>
    </asp:Panel>
    <asp:Panel ID="MainContent" runat="server">
    </asp:Panel>
</asp:Panel>

And then in the client:

<dc:CollapsiblePanelControl ID="CheckOnMePanel" runat="server" CssClass="checkonmepanel" EnableViewState="true"
        CollapsedHeight="20px" ExpandedHeight="300px" Expanded="true" HeaderText="Check On Me Email Service" >
    <Content>
        ...[Your Content Goes Here]
    </Content>
</dc:CollapsiblePanelControl>

I also wanted to create a custom control with "innerHtml". This is what I ended up with (based partially on some of the earlier answers/comments)...

div.ascx.cs:

[ParseChildren(true, "Text")] //Store inner content in Text property
public partial class div : System.Web.UI.UserControl
{
    public string Text { get; set; }
    protected void Page_Load(object sender, EventArgs e)
    {
        litText.Text = Text;  //Render it however you want
    }
}

div.ascx:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="div.ascx.cs" Inherits="TestApp.Controls.div" %>
<div>
    <asp:Literal ID="litText" runat="server" />
</div>

Test page:

<%@ register src="~/Controls/div.ascx" tagname="div" tagprefix="uc" %>
<uc:div ID="div1" runat="server">Test data</uc:div>

I believe you just need to apply a couple of attributes to the control:

[ParseChildren(false)]
[PersistChildren(true)]
public class MyDiv : UserControl
{
    ...

You may then need to override AddedControl - I'm not sure.

Put it this way - that's what works for the one and only user control I've ever written :)


The suggested solutions did not work for me. I found the following solutions: Either make your user control inherit from Panel instead of only UserControl, or if you have more than one content like in my case, make your content fields be PlaceHolders instead of simple Controls.

The [PersistenceMode(PersistenceMode.InnerProperty)] is added to avoid XHTML validation warning.

public partial class DrawerControl : UserControl
{
    [PersistenceMode(PersistenceMode.InnerProperty)]
    public PlaceHolder BodyContent { get; set; }
    [PersistenceMode(PersistenceMode.InnerProperty)]
    public PlaceHolder GripContent { get; set; }

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        phBodyContent.Controls.Add(BodyContent);
        phGripContent.Controls.Add(GripContent);
    }
}

phBodyContentand phGripContent being PlaceHolders.

This way I can use my control with any content in ASPX:

<local:Drawer ID="ctlDrawer" runat="server">
    <BodyContent>
        <!--Insert any ASP content here-->
    </BodyContent>
    <GripContent>
        <!--Insert any ASP content here-->
    </GripContent>
</local:Drawer>