Hi,
I've edited the entire answer based on our discussion. Here's a working and tested example. We have below two controls - ParentControl
and ChildControl
. ParentControl
is visible via Intellisense, where ChildControl
is only visible as a child of ParentControl
as you wanted. For simple rendering purposes, the children render as li tags and output their 'text' property. The parent control ensures each child is asked to render during its own RenderContents
event.
Child Control:
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace TestControls
{
[ToolboxItem(false), Bindable(false)]
public class ChildControl : WebControl
{
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
base.Render(writer);
//render the text property as a list item for example's sake
writer.RenderBeginTag(HtmlTextWriterTag.Li);
writer.Write(this.Text);
writer.RenderEndTag();
}
[Browsable(true)]
public string Text { get; set; }
}
}
Parent Control:
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace TestControls
{
[ToolboxData("<{0}:ParentControl runat=\"server\"></{0}:ParentControl>")]
[DefaultProperty("Children"), ParseChildren(true, "Children")]
public class ParentControl : WebControl
{
private List<ChildControl> _children;
protected override void RenderContents(HtmlTextWriter writer)
{
base.RenderContents(writer);
//create a div, and write some sample text
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.Write("Parent Control. Children:");
//create a ul, and ask each child control to render
writer.RenderBeginTag(HtmlTextWriterTag.Ul);
foreach (ChildControl child in _children)
{
child.RenderControl(writer);
}
//close all tags
writer.RenderEndTag();
writer.RenderEndTag();
}
[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public virtual List<ChildControl> Children
{
get
{
if (_children == null)
_children = new List<ChildControl>();
return _children;
}
}
}
}
In my markup, I registered the controls via namespace:
<%@ Register TagPrefix="test" Namespace="TestControls" %>
And then added some markup:
<test:ParentControl ID="test" runat="server">
<test:ChildControl ID="child" Text="Hello World from Child 1" runat="server" />
<test:ChildControl ID="child2" Text="Hello World from Child 2" runat="server" />
</test:ParentControl>
In the above markup, Intellisense picks up on the outer parent control, but does not see the child control. Once the cursor is inside the parent control, Intellisense picks up on the ChildControl
tag as desired.
The final output is:
Parent Control. Children:
* Hello World from Child 1
* Hello World from Child 2
Also , here's a good article on how the whole intellisence creation works, which I followed to create the above.
I hope this helps. You'd still have to deal with rendering at the child control level in the way you see fit for your specific controls, however the above gets you started and does meet the need of a working Intellisense model.