asp.net user-controls templating webusercontrol

asp.net - ¿Cómo agregar una plantilla a un UserControl?



user-controls templating (1)

Esta pregunta se ha hecho antes

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

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

  2. Cree una propiedad de ContentTemplate pública de tipo ITemplate :

    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>

  3. A continuación, necesitamos usar el contenido de la ContentTemplate , agregándolo en algún lugar. Lo hacemos agregándolo a uno de los elementos div 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 cosas ContentTemplate :

    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="Contoso.aspx.cs" Inherits="Contoso" %> <div id="ContentDiv" runat="server"></div>

    Luego ContentTemplate cosas de ContentTemplate en esa ContentTemplate 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; } }

  4. 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 clase UserControl como algo.

  5. 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 archivo ascx
    • 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 de uc:Contoso (yo uso uc como abreviatura para el control del usuario )
  6. 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" :

Lectura de bonos

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

Descargar el código fuente

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: