Как добавить дочерние узлы в пользовательский элемент управления asp.net, полученный из System.Web.UI.Control
Я хотел бы знать, как добавить некоторые дополнительные дочерние узлы в пользовательский класс управления, производный от System.Web.UI.Control.
Например, в настоящее время у меня есть элемент управления, который не содержит дочерних узлов и на поверхности конструктора выглядит следующим образом.
<cust:MyCustomControl id="ctlMyCustomControl" runat="server" attribute1="somevalue" attribute2="somevalue" ></MyCustomControl>
Что я ищу, так это чтобы у меня была возможность добавить n дочерних узлов к этому элементу управления из области проектирования, а затем получить доступ к их значениям из кода. Таким образом, добавление к контролю, изложенному выше.
<cust:MyCustomControl id="ctlMyCustomControl" runat="server" attribute1="somevalue" attribute2="somevalue" >
<childnode1>value1</childnode1>
<childnode2>value2</childnode2>
</MyCustomControl>
Мне не понятно, как получить доступ к дочерним узлам.
Любое понимание того, как это сделать, приветствуется.
2 ответа
Вы хотите иметь возможность декларативно описывать свойства элемента управления asp.net.
Чтобы иметь возможность иметь следующую разметку:
<Abc:CustomControlUno runat="server" ID="Control1">
<Children>
<Abc:Control1Child IntegerProperty="1" StringProperty="Item1" />
<Abc:Control1Child IntegerProperty="2" StringProperty="Item2" />
</Children>
</Abc:CustomControlUno>
Вам нужен следующий код:
[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; }
}
Если вы хотите поддерживать данный синтаксис как есть (без использования префиксов тегов), вы можете использовать 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);
}
}
Смотрите также http://msdn.microsoft.com/en-us/library/system.web.ui.controlbuilder.aspx