Pergunta

Eu tenho tentado criar um controle personalizado que funciona exatamente como o controle Panel exceto rodeado por algumas divs e tal para criar uma aparência caixa arredondada. Eu não tenho sido capaz de encontrar um exemplo decente de como fazer isso.

Eu preciso ser capaz de texto lugar e controles dentro do controle e acessá-lo diretamente, sem referência ao painel (exatamente a forma como funciona o Painel de Controle).

Alguém tem alguma exemplos disso?

Foi útil?

Solução

Há duas maneiras de fazer isso. Um deles é para implementar INamingContainer no seu controle, e é preciso muito esforço.

A outra maneira é para herdar de Panel, e substituir os métodos RenderBeginTag e RenderEndTag para adicionar a sua marcação personalizada. Isso é fácil.

public class RoundedCornersPanel : System.Web.UI.WebControls.Panel
{
    public override RenderBeginTag (HtmlTextWriter writer)
    {
        writer.Write("Your rounded corner opening markup");
        base.RenderBeginTag(writer);
    }

    public override RenderEndTag (HtmlTextWriter writer)
    {
        base.RenderEndTag(writer);
        writer.Write("Your rounded corner closing markup");                     
    }
}

Outras dicas

Há já algumas respostas aqui, mas eu só queria para colar a implementação mais básica deste sem herdar da classe Panel. Então aqui vai:

using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;

[ToolboxData("<{0}:SimpleContainer runat=server></{0}:SimpleContainer>")]
[ParseChildren(true, "Content")]
public class SimpleContainer : WebControl, INamingContainer
{
    [PersistenceMode(PersistenceMode.InnerProperty)]
    [TemplateContainer(typeof(SimpleContainer))]
    [TemplateInstance(TemplateInstance.Single)]
    public virtual ITemplate Content { get; set; }

    public override void RenderBeginTag(HtmlTextWriter writer)
    {
        // Do not render anything.
    }

    public override void RenderEndTag(HtmlTextWriter writer)
    {
        // Do not render anything.
    }

    protected override void RenderContents(HtmlTextWriter output)
    {
        output.Write("<div class='container'>");
        this.RenderChildren(output);
        output.Write("</div>");
    }

    protected override void OnInit(System.EventArgs e)
    {
        base.OnInit(e);

        // Initialize all child controls.
        this.CreateChildControls();
        this.ChildControlsCreated = true;
    }

    protected override void CreateChildControls()
    {
        // Remove any controls
        this.Controls.Clear();

        // Add all content to a container.
        var container = new Control();
        this.Content.InstantiateIn(container);

        // Add container to the control collection.
        this.Controls.Add(container);
    }
}

Em seguida, você pode usá-lo como este:

<MyControls:SimpleContainer
    ID="container1"
    runat="server">
    <Content>
        <asp:TextBox
            ID="txtName"
            runat="server" />

        <asp:Button
            ID="btnSubmit"
            runat="server"
            Text="Submit" />
    </Content>
</MyControls:SimpleContainer>

E a partir codebehind você pode fazer coisas como esta:

this.btnSubmit.Text = "Click me!";
this.txtName.Text = "Jack Sparrow";

Crie uma classe que herda System.Web.UI.Control e sobrescrevam o método Render (HtmlTextWriter). Neste método, tornar circundante tags de início, em seguida, tornar as crianças (RenderChildren), em seguida, processar tags finais.

protected override void Render ( HtmlTextWriter output )
{
  output.Write ( "<div>" );
  RenderChildren ( output );
  output.Write ( "</div>" );
}

Os cantos arredondados é tipicamente alcançado usando CSS e imagens de canto para o canto superior esquerdo, superior direito, inferior esquerdo e direito cantos inferiores. Pode ser feito usando 4 divs aninhadas, atuando como camadas, cada um deles com imagem um canto como sua imagem de fundo.

projeto de código tem algo que pode interessar a você: Painel Curve Container - Um ASP .NET personalizado Controle Nugget . Tenho certeza que você pode jogar com o código e ter o comportamento e aparência desejada.

text alt

Se você não quer herdar diretamente de WebControl em vez do painel, a maneira mais fácil de fazer isso é para decorar a classe com o [ParseChildren(false)] atributo. Embora à primeira vista isso pode sugerir que você não quer para analisar as crianças, o que o false realmente indica é que você não quer que as crianças sejam tratadas como propriedades. Em vez disso, você quer que eles sejam tratados como controles.

Ao utilizar este atributo, você tem praticamente toda a funcionalidade fora da caixa:

[ToolboxData("<{0}:RoundedBox runat=server></{0}:RoundedBox>")]
[ParseChildren(false)]
public class RoundedBox : WebControl, INamingContainer
{
    public override void RenderBeginTag(HtmlTextWriter writer)
    {
        writer.Write("<div class='roundedbox'>");
    }

    public override void RenderEndTag(HtmlTextWriter writer)
    {
        writer.Write("</div>");
    }
}

Isso permitirá que você adicionar controles RoundedBox às suas páginas, e adicionar as crianças (quer controles ASP.NET ou HTML puro) que serão prestados dentro de sua div.

Claro, css seria adicionado corretamente estilo da classe roundedbox.

Apenas uma outra coisa que você pode usar, há um arredondada extensor de canto no ajax toolkit de ASP.Net.

Eu sei que não é exatamente o que você pediu, mas você não tem que escrever qualquer código personalizado.

Espero que ajude!

Eu olhei para esta pergunta, porque eu queria produzir um painel de layout 2 coluna. (Não muito, mas é um muito mais simples exemplo do que eu precisava estou compartilhando a solução que acabei usando:.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Syn.Test
{
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:MultiPanel runat=server></{0}:MultiPanel>")]
    [ParseChildren(true)]
    [PersistChildren(false)]
    public class MultiPanel : WebControl, INamingContainer
    {
        public ContentContainer LeftContent { get; set; }

        public ContentContainer RightContent { get; set; }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
        }

        protected override void Render(HtmlTextWriter output)
        {
            output.AddStyleAttribute("width", "600px");
            output.RenderBeginTag(HtmlTextWriterTag.Div);

            output.AddStyleAttribute("float", "left");
            output.AddStyleAttribute("width", "280px");
            output.AddStyleAttribute("padding", "10px");
            output.RenderBeginTag(HtmlTextWriterTag.Div);
            LeftContent.RenderControl(output);
            output.RenderEndTag();

            output.AddStyleAttribute("float", "left");
            output.AddStyleAttribute("width", "280px");
            output.AddStyleAttribute("padding", "10px");
            output.RenderBeginTag(HtmlTextWriterTag.Div);
            RightContent.RenderControl(output);
            output.RenderEndTag();

            output.RenderEndTag();
         }
    }

    [ParseChildren(false)]
    public class ContentContainer : Control, INamingContainer
    {
    }
}

O problema que ainda tem é o trabalho intellisense does't para neste cenário, não irá sugerir a esquerda ea direita etiquetas de conteúdo.

public class myCustomPanel : Panel
{
    public override void RenderBeginTag(HtmlTextWriter writer)
    {
        writer.AddAttribute(HtmlTextWriterAttribute.Class, "top_left_corner");
        writer.RenderBeginTag(HtmlTextWriterTag.Div);
            base.RenderBeginTag(writer);
    }

    public override void RenderEndTag(HtmlTextWriter writer)
    {
            base.RenderEndTag(writer);
        writer.RenderEndTag();
    }

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