Я отредактировал весь ответ на основе на нашем обсуждении. Вот пример работы и тестирования. У нас есть два элемента управления: ParentControl
и ChildControl
. ParentControl
видна через Intellisense, где ChildControl
видна только в виде ребенка ParentControl
, как вы хотели. Для простых целей рендеринга дети отображают как теги li и ou tput их свойство «текст». Родительский элемент управления обеспечивает, чтобы каждый ребенок попросил отобразить его во время своего собственного события RenderContents
.
Контроль за детьми: Контроль
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; }
}
}
Родитель:
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;
}
}
}
}
В моей разметке я регистрировал управления с помощью пространства имен:
<%@ Register TagPrefix="test" Namespace="TestControls" %>
А потом добавил некоторые разметка:
<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>
В вышеуказанной разметке Intellisense берет на себя внешний элемент управления, но не видит дочернего элемента управления. Когда курсор находится внутри родительского элемента управления, Intellisense подбирает тег ChildControl
по желанию.
Конечный результат:
Родительский контроль. Дети:
* Hello World from Child 1
* Hello World from Child 2
Кроме того, вот good article on how the whole intellisence creation works, который я последовал за создание выше.
Надеюсь, это поможет. Вам все равно придется иметь дело с рендерингом на уровне контроля над детьми так, как вы считаете нужным для ваших конкретных элементов управления, однако приведенное выше вы начинаете и действительно отвечаете потребностям рабочей модели Intellisense.
к моему субконтролю Я добавил [ToolboxItem (false)], затем я выставил его как свойство родительского элемента управления с атрибутом [PersistenceMode (PersistenceMode.InnerProperty)]. Я думаю, что это не «правильный» способ сделать это, но в это время единственный, кто делает трюк ... – tanathos
Почему это «неправильный» способ? Я верю, что ты на правильном пути. Другой пример, использующий те же атрибуты: http://www.robertwray.co.uk/blog/2008/02/describing-aspnet-control-properties-declaratively.html –
, потому что таким образом мой вспомогательный элемент управления не отображается автоматически, это просто свойство его родителя, я должен реализовать логику визуализации на родительском уровне ... честно говоря, я не понимаю, как работают asp: TableRow и asp: Table, я вижу их код в отражателе, но я не нашел причины, которая делает TableRow невидимым за пределами таблицы .... – tanathos