Я отредактировал весь ответ на основе нашего обсуждения. Вот рабочий и проверенный пример. У нас есть два элемента управления - ParentControl
и ChildControl
. ParentControl
отображается через Intellisense, где ChildControl
отображается только как дочерний элемент ParentControl
, как вы хотели. Для простых целей визуализации дочерние элементы визуализируются как теги li и выводят свое свойство text. Родительский элемент управления гарантирует, что каждому дочернему элементу будет предложено выполнить рендеринг во время его собственного 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
Кроме того, вот хорошая статья о том, как работает весь процесс создания интеллекта, по которой я создал выше.
Надеюсь, это поможет. Вам все равно придется иметь дело с рендерингом на уровне дочерних элементов управления так, как вы считаете нужным для ваших конкретных элементов управления, однако приведенное выше дает вам начало и действительно удовлетворяет потребность в рабочей модели Intellisense.
person
KP.
schedule
09.02.2010