How to add child nodes to custom asp.net user control derived from System.Web.UI.Control
Asked Answered
S

2

6

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 looks 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.

Syncopated answered 4/9, 2010 at 14:50 Comment(3)
I've given an answer that's nearly what you're after markup wise - let me know if you must have the markup in the format you've shown. I think it's do-able and will have a root around for you to see if I've got an answer for it somewhere =)Cottonwood
@Rob, this is exactly what I was looking for, and actually the extra parent node "Children" is imo better as you can be more explicit about what the children nodes represent. Thank you so much!!Syncopated
no problemo, glad I could help =) (And I agree with you re: the extra parent node)Cottonwood
C
6

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; }
}
Cottonwood answered 4/9, 2010 at 15:1 Comment(0)
D
4

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

Damselfish answered 4/9, 2010 at 15:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.