2008-11-20 24 views
13

He estado tratando de crear un control personalizado que funcione exactamente igual que el control Panel, excepto rodeado por unos pocos divs y tal para crear un aspecto de cuadro redondeado. No he podido encontrar un ejemplo decente de cómo hacer esto.Control de contenedor personalizado ASP.NET

tengo que ser capaz de poner el texto y los controles dentro del control y acceder a ella directamente sin hacer referencia al panel (exactamente como funciona el control Panel).

¿Alguien tiene algún ejemplo de esto?

Respuesta

15

Hay dos formas de hacerlo. Una es implementar INamingContainer en su control, y requiere un gran esfuerzo.

La otra forma es heredar de panel, y anular los métodos RenderBeginTag y RenderEndTag añadir su marcado personalizado. Esto es facil.

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");      
    } 
} 
+0

Esta es probablemente una pregunta muy estúpida, pero como no puedo colocar este código en un control de usuario típico (.ascx), ¿dónde lo pondría? Creé una clase y la coloqué allí, pero no sé cómo agregarla a una página (arrastrar solo crea un enlace) –

+0

Publicar una pregunta sobre cómo usar los controles del Servidor ASP.NET, y puedo responder, No puedo incluir la explicación en este pequeño cuadro de comentarios. – FlySwat

+0

Si compila el código, aparecerá en la caja de herramientas. –

3

crear una clase que hereda System.Web.UI.Control y overrride el método Render (HtmlTextWriter). En este método, renderice las etiquetas de inicio circundantes, luego renderice los elementos secundarios (RenderChildren), luego renderice las etiquetas finales.

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

Las esquinas redondeadas se logra típicamente usando CSS y esquina imágenes de la parte superior izquierda, superior derecha, inferior esquinas izquierda e inferior derecha. Podría hacerse usando 4 divs anidados, que actúan como capas, cada uno de ellos con una imagen de esquina como imagen de fondo.

-1
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(); 
    } 

} 
0

Sólo otra cosa que se puede utilizar, hay una rounded corner extender en el kit de herramientas AJAX ASP.Net.

Sé que no es exactamente lo que pediste, pero no tienes que escribir ningún código personalizado.

Espero que ayude!

13

Ya hay bastantes respuestas aquí, pero solo quería pegar la implementación más básica de esto sin heredar de la clase Panel. Así que aquí va:

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

A continuación, se puede utilizar de esta manera:

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

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

Y de código subyacente que puede hacer cosas como esta:

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

Buen ejemplo. Funciona para mi. –

+0

Gracias. Trabajó para mi. –

+0

¿Cómo cambiarías la clase SimpleContainer si el objetivo era tener un contenido izquierdo y un contenido correcto? ¿Podría simplemente tener 2 propiedades ITemplate? ¿Qué pasa con el atributo ParseChildren? – SynBiotik

0

Miré a esta pregunta porque Quería producir un panel de diseño de 2 columnas. (No del todo, pero es un ejemplo mucho más simple de lo que tenía que estoy compartiendo la solución que terminé 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 
    { 
    } 
} 

La cuestión es que todavía tengo la intelisense does't de trabajo en este escenario, no sugerirá las etiquetas de contenido izquierda y derecha.

2

Si no desea heredar directamente de WebControl en lugar de desde el Panel, la manera más fácil de hacerlo es decorar la clase con el atributo [ParseChildren(false)]. Aunque a primera vista esto podría sugerir que no desea analizar los elementos secundarios, lo que el false realmente indica es que no desea que los elementos secundarios sean tratados como propiedades. En cambio, desea que se los trate como controles.

Mediante el uso de este atributo, se obtiene prácticamente toda la funcionalidad de la caja:

[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>"); 
    } 
} 

Esto le permitirá añadir controla RoundedBox a sus páginas, y agregar los niños (ya los controles ASP.NET o raw html) que se representará dentro de su div.

Por supuesto, se agregarán css para el estilo correcto de la clase roundedbox.

Cuestiones relacionadas