views:

1415

answers:

3

I am having an issue with a custom control rendering its contents (child controls) outside of the tag which leads to runtime errors and issues. In an attempt to simplify things as much as I can, I created the control below but it has the very same issue. I have tried inheriting from Control, WebControl and CompositeControl all resulting in with the same problem. Guessing there is something obvious that I am doing wrong... Thanks for any help.

using System;
using System.Web.UI.WebControls;

namespace MyControls
{
    public class TestControl : CompositeControl
    {
        protected override void CreateChildControls()
        {
            Controls.Clear();
            Controls.Add(new Button() { Text = "TestControl!" });
            ClearChildViewState();
        }
    }
}

Adding the control programmatically results in markup outside the forms tag. Adding the control via markup works correct.

protected void Page_Load(object sender, EventArgs e)
{
    Controls.Add(new TestControl());
}



...
<body>
    <form name="PageForm" method="post" action="default.aspx" id="PageForm">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTE5MDEwMTE5MWRkg0FopdvLhTPGxHkGm1xCCOVQz6A=" />
</div>

    <div>

    </div>
    </form>
</body>
</html>
<span><input type="submit" name="ctl04$ctl00" value="TestControl!" /></span>
A: 

Your control seems ok, I think you have a problem with adding your control to your page,

Add a placeHolder to your page,

<body>
    <form id="form1" runat="server">
    <div>
     <asp:PlaceHolder ID="placeHolder" runat="server"></asp:PlaceHolder>
    </div>
    </form>
</body>

and then add your composite control to this placeholder's controls collection like that :

TestControl testCtrl = new TestControl();
placeHolder.Controls.Add(testCtrl);
Canavar
I think in theory this will work but it doesn't make a custom control very general purpose. Certainly not the way other custome controls work.
Andrew Robinson
I wonder how you add your control to your page ? do you drag and drop into the form tags ?
Canavar
Sorry. Being added programmatically. Works fine when added in the markup.
Andrew Robinson
Why is it necessary to add the control pro grammatically?
Robert C. Barth
A: 

Adding the control through the Page.Form property will render the button inside the form.

Page.Form.Controls.Add(new Button() { Text = "TestControl!" });

However, since the button is not contained within a block, such as a <div>, you might have some layout issues with this button. Use ScarletGarden's approach.

baretta
I agree that this will work but it is not very intuitive especially if someone else is using the control and doesn't know better. How come other custom controls don't requite this approach?Controls.Add(new Button());works just fine. My control doesn't. What am I missing?
Andrew Robinson
It's more common to include controls using declarative markup, then manually adding controls to the ControlCollection. You could associate the MyControls namespace with a tag prefix and then use em like: <my:TestControl ID="test" runat="server" /> otherwise, give more information on your problem
baretta
+2  A: 

This has nothing to do with your custom control. Your problem is caused by how you're adding the control to the page.

When you call Controls.Add in your page's Page_Load method, this is basically shorthand for:

Page.Controls.Add(new TestControl());

ie, You're adding the control at the end of your entire page's control hierarchy. When the page is rendered, your control is rendered after all the others - even after the closing </html> tag.

If you want your control to be rendered inside the form then you need to add it to the form's control hierarchy instead:

Form.Controls.Add(new TestControl());

If you need even more fine-grained positioning, then you need to put a placeholder (or div or span etc) on your page in the required position and add your control to that, as in ScarletGarden's answer.

LukeH
Ok. I was definitely off in the wrong direction. I assumed that standard asp.net controls worked differently than mine did but they exhibit the same issue when added to the Page.Controls collection. My bad assumption.
Andrew Robinson