2009-11-10 21 views
8

Estoy escribiendo un poco de código para agregar una etiqueta de enlace de la etiqueta de la cabeza en el código detrás ... es decirSelf-closing Html Generic Control?

HtmlGenericControl css = new HtmlGenericControl("link"); 

css.Attributes["rel"] = "Stylesheet"; 
css.Attributes["type"] = "text/css"; 
css.Attributes["href"] = String.Format("/Assets/CSS/{0}", cssFile); 

para tratar de lograr algo como ...

<link rel="Stylesheet" type="text/css" href="/CSS/Blah.css" /> 

I estoy utilizando el HtmlGenericControl para lograr esto ... el problema que estoy teniendo es que el control ultimatly se representa como ...

<link rel="Stylesheet" type="text/css" href="/CSS/Blah.css"></link> 

me parece que no puede encontrar lo que me falta para no hacer que el complemento Iional </link>, supuse que debería ser una propiedad del objeto.

¿Me falta algo o simplemente no es posible con este control?

Gracias

+0

¿Algún motivo en particular para el formato abreviado? Para uno o tal vez un puñado de enlaces por página, creo que la sobrecarga de un puñado de bytes sería insignificante. – Lazarus

+2

Porque usar la forma larga de algunas etiquetas causa problemas en algunos navegadores. Es una buena idea. Algunas versiones (¿quizás todas?) De IE no soportan

erikkallen

+0

@Lazarus: erikkallen es correcto con el problema del navegador, quiero asegurar la mejor compatibilidad. –

Respuesta

9

creo que tendría que derivar de HtmlGenericControl, y reemplazar el método Render.

Luego podrá escribir el "/>" usted mismo (o puede usar la constante SelfClosingTagEnd de HtmlTextWriter).

Editar: Here's an example (en VB)

1

Alternativamente, puede utilizar Page.ParseControl(string), que le da un control con el mismo contenido que la cadena se pasa.

De hecho, estoy haciendo exactamente lo mismo en mi proyecto actual. Por supuesto, requiere una referencia a la página actual (el controlador), pero eso no debería plantear ningún problema.

La única salvedad en este método, tal como lo veo, es que usted no recibe ninguna -enfoque "OO" para la creación de su control (por ejemplo. control.Attributes.Add("href", theValue") etc.)

0

simplemente he creado una solución para esto, basado en Ragaraths comentarios en otro foro:

http://forums.asp.net/p/1537143/3737667.aspx

Sustituir el HtmlGenericControl con este

protected override void Render(HtmlTextWriter writer) 
{ 
    if (this.Controls.Count > 0) 
     base.Render(writer); // render in normal way 
    else 
    { 
     writer.Write(HtmlTextWriter.TagLeftChar + this.TagName); // render opening tag 
     Attributes.Render(writer); // Add the attributes. 
     writer.Write(HtmlTextWriter.SelfClosingTagEnd); // render closing tag 
    } 

    writer.Write(Environment.NewLine); // make it one per line 
} 
8

Al intentar escribir una solución para umbraco.library:RegisterStyleSheetFile(string key, string url) terminé con la misma pregunta que el OP y encontré lo siguiente.

De acuerdo con specs, la etiqueta es un elemento nulo. No puede tener ningún contenido, pero puede ser de cierre automático. El validador W3C no validó <link></link> como html5 correcto.

Al parecer

HtmlGenericControl css = new HtmlGenericControl("link"); 

se rinde por defecto como <link></link>.Usando el control específico para el enlace etiqueta resolvió mi problema:

HtmlLink css = new HtmlLink(); 

Produce el margen de <link/> que fue validado como XHTML y HTML5 correcta.

Además de enlace, System.Web.UI.HtmlControls contiene clases para otros controles de elementos huecos, tales como img, entrada y meta.

+1

Esta es claramente la manera más limpia de producir html válido ... ¿por qué usar el control genérico cuando se proporciona una clase HtmlLink? – Nick

0

ligeramente hacky way.

  • coloca el control dentro de un elemento marcador de posición.
  • En el código detrás de secuestrar el método de representación del PlaceHolder.
  • Renderice el contenido de PlaceHolders exactamente como lo desee.

Esto es específico de la página/control y no requiere ninguna anulación. Por lo tanto, tiene un impacto mínimo en el resto de su sistema.

<asp:PlaceHolder ID="myPlaceHolder" runat="server"> 
    <hr id="someElement" runat="server" /> 
</asp:PlaceHolder> 

protected void Page_Init(object sender, EventArgs e) 
{ 
    myPlaceHolder.SetRenderMethodDelegate(ClosingRenderMethod); 
} 

protected void ClosingRenderMethod(HtmlTextWriter output, Control container) 
{ 
    var voidTags = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase) { "br", "hr", "link", "img" }; 
    foreach (Control child in container.Controls) 
    { 
     var generic = child as HtmlGenericControl; 
     if (generic != null && voidTags.Contains(generic.TagName)) 
     {     
      output.WriteBeginTag(generic.TagName); 
      output.WriteAttribute("id", generic.ClientID); 
      generic.Attributes.Render(output); 
      output.Write(HtmlTextWriter.SelfClosingTagEnd);     
     } 
     else 
     { 
      child.RenderControl(output); 
     } 
    } 
}