asp.net - mvc5 - render partial asp net core
Control de contenedor ASP.NET personalizado (8)
He intentado crear un control personalizado que funcione exactamente igual que el control del 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.
Necesito poder colocar texto y controles dentro del control y acceder directamente sin tener que hacer referencia al panel (exactamente como funciona el control del Panel).
¿Alguien tiene algún ejemplo de esto?
Cree una clase que herede System.Web.UI.Control y anule el método Render (HtmlTextWriter). En este método, renderice las etiquetas de inicio circundantes, luego renderice los elementos secundarios (RenderChildren) y luego renderice las etiquetas finales.
protected override void Render ( HtmlTextWriter output )
{
output.Write ( "<div>" );
RenderChildren ( output );
output.Write ( "</div>" );
}
Las esquinas redondeadas generalmente se logran utilizando CSS e imágenes de esquina para las esquinas superior izquierda, superior derecha, inferior 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.
Hay dos formas de hacer esto. Una es implementar INamingContainer en su control, y requiere un gran esfuerzo.
La otra forma es heredar del Panel y anular los métodos RenderBeginTag y RenderEndTag para agregar 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");
}
}
Solo otra cosa que puede usar, hay un extensor de esquina redondeado en el kit de herramientas ASP.Net ajax.
Sé que no es exactamente lo que pediste, pero no tienes que escribir ningún código personalizado.
¡Espero que ayude!
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();
}
}
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);
}
}
Entonces puedes usarlo así:
<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 desde código subyacente puedes hacer cosas como esta:
this.btnSubmit.Text = "Click me!";
this.txtName.Text = "Jack Sparrow";
Miré 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 necesitaba. 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
{
}
}
El problema que aún tengo es que el intellisense no funciona en este escenario, no sugerirá las etiquetas de contenido izquierda y derecha.
Si no desea heredar directamente de WebControl en lugar de desde el Panel, la forma más sencilla de hacerlo es decorar la clase con el atributo [ParseChildren(false)]
. Aunque a primera vista esto podría sugerir que no desea analizar niños, lo que realmente indica el false
es que no desea que los niños sean tratados como propiedades. En cambio, desea que se los trate como controles.
Al usar este atributo, obtienes prácticamente toda la funcionalidad lista para usar:
[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á agregar controles RoundedBox a sus páginas, y agregar elementos secundarios (ya sean controles asp.net o html sin procesar) que se procesarán dentro de su div.
Por supuesto, css se agregaría para darle un estilo correcto a la clase de recuadro redondeado.
El proyecto de código tiene algo que podría interesarle: Panel Curve Container - Un Nugget de control personalizado de ASP.NET . Estoy seguro de que puedes jugar con el código y tener el comportamiento y la apariencia que deseas.