asp.net - ¿Cómo agregar una plantilla a un UserControl?
user-controls templating (1)
Esta pregunta se ha hecho antes
- Formularios web :: Soporte en tiempo de diseño para el control de usuario personalizado según plantilla en VS 2008
- VS 2008 Usar la plantilla de IT en un UserControl y obtener un error de representación del tiempo de diseño
- ¿Cómo mostrar los controles para el control del usuario web en tiempo de diseño?
- UserControl ITemplate Error de tiempo de diseño de propiedad: fácil para un gurú ...
Pero no hace daño volver a preguntarlo:
¿Cómo agrego plantillas a un
UserControl
en ASP.net?
Lo que no ha funcionado hasta ahora
Comience con un nuevo
UserControl
5 , al que llamaréContoso
:public partial class Contoso: System.Web.UI.UserControl { }
Esto nos permitirá utilizar un nuevo control: 1
<Contoso> Stuff in here <Contoso>
Cree una propiedad de
ContentTemplate
pública de tipoITemplate
:public partial class Contoso: System.Web.UI.UserControl { public ITemplate ContentTemplate { get; set; } }
y agregue un número indeterminado de atributos a la propiedad
ContentTemplate
: 2//[ParseChildren(true)] [ParseChildren(true, "ContentTemplate")] //[ParseChildren(false)] public partial class Contoso: System.Web.UI.UserControl { [TemplateContainer(typeof(ContentContainer))] [TemplateInstance(TemplateInstance.Single)] [PersistenceMode(PersistenceMode.InnerProperty)] //[PersistenceMode(PersistenceMode.InnerDefaultProperty)] [Browsable(true)] //[Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] //[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public ITemplate ContentTemplate { get; set; } }
esto nos permitirá agregar
<ContentTemplate>
al control en nuestro archivo aspx: 1<Contoso> <ContentTemplate> Stuff in here </ContentTemplate> </Contoso>
A continuación, necesitamos usar el contenido de la
ContentTemplate
, agregándolo en algún lugar. Lo hacemos agregándolo a uno de los elementosdiv
internos de nuestro UserControl.A partir de nuestro archivo
.aspx
que originalmente estaba vacío:<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Contoso.aspx.cs" Inherits="Contoso" %>
añadimos un
div
padre que contendrá nuestras cosasContentTemplate
:<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Contoso.aspx.cs" Inherits="Contoso" %> <div id="ContentDiv" runat="server"></div>
Luego
ContentTemplate
cosas deContentTemplate
en esaContentTemplate
principal durante el inicio del control:public partial class Contoso: System.Web.UI.UserControl { protected override void OnInit(EventArgs e) { base.OnInit(e); //If there''s content, then put it into our ContentDiv div if (this.ContentTemplate != null) this.ContentTemplate.InstantiateIn(ContentDiv); } [PersistenceModeAttribute(PersistenceMode.InnerProperty)] [TemplateInstanceAttribute(TemplateInstance.Single)] [Browsable(true)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public ITemplate ContentTemplate { get; set; } }
Editar : Indique que su clase implementa
INamingContainer
:public partial class Contoso: System.Web.UI.UserControl: INamingContainer { protected override void OnInit(EventArgs e) { base.OnInit(e); //If there''s content, then put it into our ContentDiv div if (this.ContentTemplate != null) this.ContentTemplate.InstantiateIn(ContentDiv); } [PersistenceModeAttribute(PersistenceMode.InnerProperty)] [TemplateInstanceAttribute(TemplateInstance.Single)] [Browsable(true)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public ITemplate ContentTemplate { get; set; } }
La interfaz
INamingContainer
no tiene miembros, y solo se usa para marcar su claseUserControl
como algo.Y hemos terminado 3 . Ahora podemos usar este control en nuestra página aspx. Pero primero necesitamos "registrarlo" en la parte superior de nuestra página aspx:
<%@ Register src="Contoso.ascx" TagName="Contoso" tagprefix="uc" %>
Dónde:
-
Contoso.ascx
es el nombre del archivoascx
-
Contoso
es el nombre del elemento que usaremos para hacer referencia a este control de usuario -
uc
es un poco de texto que tendremos que poner delante deuc:Contoso
(yo usouc
como abreviatura para el control del usuario )
-
Agregue el control a nuestra página:
<uc:Contoso ID="Crackers" runat="server"> <ContentTemplate> Stuff goes here </ContentTemplate> </qwerty:Contoso>
¡Y hemos terminado! 4
Editar : Olvidé agregar la razón por la que lo anterior no funciona. Visual Studio muestra el error:
Error al crear el control - Crackers
El tipo ''System.Web.UI.UserControl'' no tiene una propiedad pública llamada ''ContentTemplate''
Lo que tiene sentido, ya que UserControl
no tiene una propiedad pública llamada ContentTemplate
, por lo que no puedo culparlo.
Serie
Esta pregunta es una de las series de Stackoverflow en curso, "Plantillas de controles de usuario" :
- ¿Cómo agregar una plantilla a un UserControl?
- ¿Cómo heredar de Control, en lugar de UserControl?
- UserControl tiene IsPostBack, pero Control no
- UserControl no tiene propiedad pública llamada ContentTemplate
- ¿Cómo puedo especificar CodeFileBaseClass desde web.config?
Lectura de bonos
- Cómo crear controles de usuario de ASP.NET con plantilla
- Creación de un control de usuario con plantilla con ASP.Net 2.0
- Controles de usuario con plantillas en ASP.NET para un mejor mantenimiento
Notas al pie
- 1 Nunca puedes usar esa sintaxis. Es solo una forma fácil de leer y entender.
- 2 Nadie sabe qué atributos agregar, o por qué. Añadir más o menos atributo al gusto.
- 3 No hecho. Hecho con el UserControl, pero no con nuestro trabajo.
- 4 No hecho; no funciona
- 5 en el sitio web (no es una aplicación web, no en un ensamblaje separado)
Bueno, creo que casi lo tienes.
Por cierto El UserControl no se procesa con Visual Studio Designer, sin embargo, cuando ejecuta la aplicación, el control funciona. Esto es diferente si usa los controles del servidor, en ese caso, el control se muestra correctamente en el diseñador de Visual Studio.
El siguiente código funciona muy bien para crear controles de usuario con plantilla y controles de servidor con plantilla. Sin embargo, si desea agregar capacidades de enlace, el proceso es ligeramente diferente, eche un vistazo
Este es el código para crear un UserControl
plantilla.
Salida simple
Contenedor de plantillas
public class MyTemplateContainer : Control, INamingContainer { }
Código ASPX detrás
protected void Page_Load(object sender, EventArgs e)
{
// just to demonstrate using the contorl
this.WebUserControl1.Controls.Add(new LiteralControl("<br />new control"));
}
ASPX
<%@ Register src="WebUserControl.ascx" tagname="WebUserControl" tagprefix="uc1" %>
<uc1:WebUserControl ID="WebUserControl1" runat="server">
<ContentTemplate>
My Template<br />
<asp:Label Text=''Hello People'' runat="server" ID="lblMessage" />
</ContentTemplate>
</uc1:WebUserControl>
Código ASCX detrás
public partial class WebUserControl : System.Web.UI.UserControl
{
[TemplateContainer(typeof(MyTemplateContainer))]
[TemplateInstance(TemplateInstance.Single)]
[PersistenceMode(PersistenceMode.InnerProperty)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public ITemplate ContentTemplate { get; set; }
protected void Page_Init(object sender, EventArgs e)
{
this.myPlaceHolderTag.Controls.Clear();
if (this.ContentTemplate != null)
{
var container = new MyTemplateContainer();
this.ContentTemplate.InstantiateIn(container);
this.myPlaceHolderTag.Controls.Add(container);
}
else
{
this.myPlaceHolderTag.Controls.Add(new LiteralControl("No template defined"));
}
}
}
ASCX
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="WebUserControl.ascx.cs" Inherits="WebUserControl" %>
<asp:PlaceHolder runat="server" ID="myPlaceHolderTag" />
Código para agregar un control de servidor con plantilla
Salida
ASPX
<%@ Register Namespace="MyControls" TagPrefix="my" %>
<my:MyServerControl runat="server" ID="myServerControl">
<ContentTemplate>
My Server templated control<br />
<asp:Label Text="My Label" runat="server" />
</ContentTemplate>
</my:MyServerControl>
Contenedor de plantillas
namespace MyControls
{
[ToolboxItem(false)]
public class MyTemplateContainer : Control, INamingContainer { }
}
Control de servidor templado
namespace MyControls
{
[ToolboxData("<{0}:MyServerControl runat=server >")]
[ToolboxItem(true)]
[ParseChildren(true)]
// you can inherit from another control if you like, for example from the CompositeControl
public class MyServerControl : Control, INamingContainer
{
[TemplateInstance(TemplateInstance.Multiple)]
[TemplateContainer(typeof(MyTemplateContainer))]
[PersistenceMode(PersistenceMode.InnerProperty)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[DefaultValue(null)]
public ITemplate ContentTemplate { get; set; }
protected override void CreateChildControls()
{
var p = new Panel { ID = "myPanel", BackColor = Color.Silver, Width = new Unit("100%") };
if (this.ContentTemplate == null)
{
p.Controls.Add(new LiteralControl("No content has been specified"));
}
else
{
var c = new MyTemplateContainer();
this.ContentTemplate.InstantiateIn(c);
p.Controls.Add(c);
}
this.Controls.Clear();
this.Controls.Add(p);
}
public override void DataBind()
{
this.CreateChildControls();
this.ChildControlsCreated = true;
base.DataBind();
}
public override ControlCollection Controls
{
get
{
this.EnsureChildControls();
return base.Controls;
}
}
}
}
Referencias: