How to add child nodes to custom asp.net user control derived from System.Web.UI.Control
I would like to know how to add some additional child nodes to a custom user control class derived from System.Web.UI.Control.
For example currently I have a control that contains no child nodes and on the design surface lo开发者_高级运维oks like the following.
<cust:MyCustomControl id="ctlMyCustomControl" runat="server" attribute1="somevalue" attribute2="somevalue" ></MyCustomControl>
What I am looking for is to have the ability to add n number of child nodes to this control from the design surface and then access their values from the code. So adding to the control stated above.
<cust:MyCustomControl id="ctlMyCustomControl" runat="server" attribute1="somevalue" attribute2="somevalue" >
<childnode1>value1</childnode1>
<childnode2>value2</childnode2>
</MyCustomControl>
It is not clear to me how to access the child nodes.
Any insight on how to do this is appreciated.
You want to be able to describe asp.net control properties declaratively.
To be able to have the following markup:
<Abc:CustomControlUno runat="server" ID="Control1">
<Children>
<Abc:Control1Child IntegerProperty="1" StringProperty="Item1" />
<Abc:Control1Child IntegerProperty="2" StringProperty="Item2" />
</Children>
</Abc:CustomControlUno>
You need the following code:
[ParseChildren(true)]
[PersistChildren(true)]
[ToolboxData("<{0}:CustomControlUno runat=server></{0}:CustomControlUno>")]
public class CustomControlUno : WebControl, INamingContainer
{
private Control1ChildrenCollection _children;
[PersistenceMode(PersistenceMode.InnerProperty)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Control1ChildrenCollection Children
{
get
{
if (_children == null)
_children = new Control1ChildrenCollection();
return _children;
}
}
}
public class Control1ChildrenCollection : List<Control1Child>
{
}
public class Control1Child
{
public int IntegerProperty { get; set; }
private string StringProperty { get; set; }
}
If you wanted to support the given syntax as-is (without having to use the tag prefixes), you could use a ControlBuilder:
//MyControlBuilder
public class MyControlBuilder : ControlBuilder
{
public override Type GetChildControlType(string tagName, IDictionary attribs)
{
if (tagName.StartsWith("childnode")) return typeof(Control);
else return base.GetChildControlType(tagName,attribs);
}
public override void AppendLiteralString(string s)
{
//ignore literals betwen tags
}
}
//MyCustomControl
[ParseChildren(false)]
[ControlBuilder(typeof(MyControlBuilder))]
public class MyCustomControl : Control
{
public string attribute1 {get;set;}
public string attribute2 {get;set;}
protected override void AddParsedSubObject(object obj)
{
Control ctrl = (Control) obj;
LiteralControl childNode = ctrl.Controls[0];
//Add as-is (e.g., literal "value1")
Controls.Add(childNode);
}
}
See also http://msdn.microsoft.com/en-us/library/system.web.ui.controlbuilder.aspx
精彩评论