Give Markup support for Custom server control with public PlaceHolders properties

Posted by ravinsp on Stack Overflow See other posts from Stack Overflow or by ravinsp
Published on 2010-05-02T10:36:00Z Indexed on 2010/05/02 10:48 UTC
Read the original article Hit count: 236

I have a custom server control with two public PlaceHolder properties exposed to outside. I can use this control in a page like this:

<cc1:MyControl ID="MyControl1" runat="server">
    <TitleTemplate>
        Title text and anything else
    </TitleTemplate>

    <ContentTemplate>
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <asp:Button ID="Button1" runat="server" Text="Button" />
    </ContentTemplate>
</cc1:MyControl>

TitleTemplate and ContentTemplate are properties of type asp.net PlaceHolder class. Everything works fine. The control gets any content given to these custom properties and produces a custom HTML output around them.

If I want a Button1_Click event handler, I can attach the event handler in Page_Load like the following code. And it works.

protected void Page_Load(object sender, EventArgs e)
{
    Button1.Click += new EventHandler(Button1_Click);
}

void Button1_Click(object sender, EventArgs e)
{
    TextBox1.Text = "Button1 clicked";
}

But if try to attach the click event handler in aspx markup I get an error when running the application

"Compiler Error Message: CS0117: 'ASP.default_aspx' does not contain a definition for 'Button1_Click'

<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />

AutoEventWireup is set to "true" in the page markup.

This happens only for child controls inside my custom control. I can programatically access child control correctly. Only problem is with event handler assignment from Markup. When I select the child Button in markup, the properties window only detects it as a < BUTTON>. Not System.Web.UI.Controls.Button. It also doesn't display the "Events" tab. How can I give markup support for this scenario?

Here's code for MyControl class if needed. And remember, I'm not using any ITemplate types for this. The custom properties I provide are of type "PlaceHolder".

[ToolboxData("<{0}:MyControl runat=server>" +
                    "<TitleTemplate></TitleTemplate>" +
                    "<ContentTemplate></ContentTemplate>" +
            "</{0}:MyControl>")]
public class MyControl : WebControl
{
    PlaceHolder contentTemplate, titleTemplate;

    public MyControl()
    {
        contentTemplate = new PlaceHolder();
        titleTemplate = new PlaceHolder();
        Controls.Add(contentTemplate);
        Controls.Add(titleTemplate);
    }

    [Browsable(true)]
    [TemplateContainer(typeof(PlaceHolder))]
    [PersistenceMode(PersistenceMode.InnerProperty)]
    public PlaceHolder TitleTemplate
    {
        get { return titleTemplate; }
    }

    [Browsable(true)]
    [TemplateContainer(typeof(PlaceHolder))]
    [PersistenceMode(PersistenceMode.InnerProperty)]
    public PlaceHolder ContentTemplate
    {
        get { return contentTemplate; }
    }

    protected override void RenderContents(HtmlTextWriter output)
    {
        output.Write("<div>");

        output.Write("<div class=\"title\">");
        titleTemplate.RenderControl(output);
        output.Write("</div>");

        output.Write("<div class=\"content\">");
        contentTemplate.RenderControl(output);
        output.Write("</div>");

        output.Write("</div>");
    }
}

© Stack Overflow or respective owner

Related posts about ASP.NET

Related posts about custom-server-controls