Pergunta

Estou desenvolvendo um conjunto de controles personalizados, um deles é o "pai", quaisquer outros devem ser adicionados dentro de uma propriedade ITemplate deste pai.

Mas na página, em tempo de design, eu posso ver, por intellisense, os outros controles no nível da página, e eu posso teoricamente adicioná-los em todos os lugares.

Eu quero emular o comportamento do asp: Table eo asp: TableRow, você não pode adicionar diretamente um asp: TableRow fora de um asp: Table ...

Existe uma maneira de chegar a este? Muito obrigado!

Editar : Eu parcialmente resolvido com a sugestão KP, mas se você ler o comentário não é o caminho "real" para fazer isso (eu acho). Ninguém sabe como fazer isso? : (

Foi útil?

Solução

Eu editei a resposta completa com base em nossa discussão. Aqui está um trabalho e exemplo testado. Temos abaixo dois controles - ParentControl e ChildControl. ParentControl é visível através Intellisense, onde ChildControl só é visível como um filho de ParentControl como você queria. Para fins de processamento simples, as crianças tornam como tags li e saída de sua propriedade 'text'. O controle pai assegura que cada criança é convidada a prestar durante seu próprio evento RenderContents.

Child Control:

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; }
    }
}

Parent controle:

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;
            }
        }
    }
}

Na minha marcação, registrei os controles via namespace:

<%@ Register TagPrefix="test" Namespace="TestControls" %>

E, em seguida, acrescentou alguma marcação:

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

Na marcação acima, Intellisense pega no controle pai exterior, mas não vê o controle filho. Uma vez que o cursor é no interior do controlo parental, Intellisense pega na etiqueta ChildControl como desejado.

O resultado final é:

Parent controle. Crianças:

* Hello World from Child 1
* Hello World from Child 2

Além disso, aqui está um bom artigo sobre como funciona a toda criação intellisence , que eu segui para criar o acima.

Espero que isso ajude. Você ainda tem que lidar com o processamento no nível de controle criança no caminho em que você vê o ajuste para seus controles específicos, no entanto, o acima é uma introdução e faz satisfazer a necessidade de um modelo de Intellisense trabalho.

Outras dicas

Eu tenho feito isso antes, mas eu não tenho o código disponível. Eu posso te dizer que eu descobri-lo usando refletor sobre o built-in ASP.NET controle DataGrid. I foi capaz de reverter a engenharia a relação entre a "contido" ( "linha") e "recipiente" ( "grelha"). Você tem que organizar as classes juntos em uma maneira muito específica usando atributos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top