2011-02-10 12 views
23

TagBuilder es una buena implementación para crear elementos HTML. Pero algunos elementos HTML pueden tener otros elementos (llamé como niños). No pude encontrar ninguna clase de clases de Mvc.TagBuilder anidado -como TagBuilderTree-

Pregunta; ¿Debería implementar algunas clases (TagBuilderTree y TagBuilderNode) que admitan etiquetas anidadas o me perdi algo?

Respuesta

39

Puede construir los elementos secundarios en TagBuilders separados y poner su HTML generado en el TagBuilder principal.

He aquí un ejemplo: Una <select> con algunos <option> s (ejemplo desgrasada de concisión)

TagBuilder select = new TagBuilder("select"); 

foreach (var language in languages) // never ye mind about languages 
{ 
    TagBuilder option = new TagBuilder("option"); 
    option.MergeAttribute("value", language.ID.ToString()); 

    if (language.IsCurrent) 
    { 
     option.MergeAttribute("selected", "selected"); 
    } 

    option.InnerHtml = language.Description; 
    // And now, the money-code: 
    select.InnerHtml += option.ToString(); 
} 
+0

Prefiero implementar TagBuilderTree y TagBuilderNode encapsulará etiquetas anidadas para nuestros proyectos, pero trato de encontrar la respuesta ¿por qué Razor no las sirve? Porque parece que es necesario para todos los usuarios de Razor –

+0

Se refiere a las páginas web, no a Razor. No es necesario para todos los desarrolladores; puedes usar ayudantes estáticos en su lugar. – SLaks

+0

tienes razón, hablo de la clase System.Web.Mvc.TagBuilder. No tiene relación directa con el motor Razor. Todos los motores pueden usarlo ... Me pregunto por qué no tenemos TagBuilder como árbol y debería usar TagBuilder para las etiquetas html anidadas. ¿O debería implementar mis propias clases TagBuilderTree y TagBuilderNode? –

2

bien, decidí hacer una pequeña prueba en mi propia base de código.

I compararon estos dos métodos para crear exactamente el mismo HTML final:

  1. generar manualmente el html usando un StringBuilder
  2. El uso de múltiples TagBuilders y anidando el contenido

generar manualmente el html utilizando un StringBuilder:

 

    var sb = new StringBuilder(); 
    sb.AppendLine("<div class='control-group'>"); 
    sb.AppendFormat(" <label class='control-label' for='{0}_{1}'>{2}</label>", propObj.ModelType, propObj.ModelProperty, propObj.LabelCaption); 
    sb.AppendLine(" <div class='controls'>"); 
    sb.AppendFormat(" <input id='{0}_{1}' name='{0}[{1}]' value='{2}' />", propObj.ModelType, propObj.ModelProperty, propObj.PropertyValue); 
    sb.AppendLine(" </div>"); 
    sb.AppendLine("</div>"); 

    return new HtmlString(sb.ToString()); 
 

U cantar múltiples TagBuilders y la fusión del contenido:


    TagBuilder controlGroup = new TagBuilder("div"); 
    controlGroup.AddCssClass("control-group"); 

    TagBuilder label = new TagBuilder("label"); 
    label.AddCssClass("control-label"); 
    label.InnerHtml = propObj.LabelCaption; 

    TagBuilder controls = new TagBuilder("div"); 

    TagBuilder input = new TagBuilder("input"); 
    input.Attributes["id"] = propObj.ModelType + "_" + propObj.ModelProperty; 
    input.Attributes["name"] = propObj.ModelType + "[" + propObj.ModelProperty + "]"; 
    input.Attributes["value"] = propObj.PropertyValue; 

    controls.InnerHtml += input; 

    controlGroup.InnerHtml += label; 
    controlGroup.InnerHtml += controls; 

    return new HtmlString(controlGroup.ToString()); 

Para mí, # 1 es más fácil de leer y mucho más concisa, pero puedo apreciado sin la estructura de # 2 también.

+0

# 1 también es una posible vía para la inyección de scripts si no tiene cuidado de desinfectar, solo me gustaría agregar. – Bon

+2

Creo que # 1 es más propenso a errores porque se basa en escribir correctamente el HTML con la colocación correcta de las etiquetas de cierre, comillas simples, comillas dobles, etc. Además, TagBuilder tiene más intellisense. Por ejemplo, al agregar una clase CSS, el generador de cadenas no proporcionará ninguna inteligencia para agregar una clase, mientras que TagBulder tiene el método AddCSSClass que tiene intellisense. También encuentro que el # 2 es mucho más legible. Todos los marcadores de posición en el método # 1 dejan las cosas menos claras. –

-2

El problema que tengo con TagBuilder para crear etiquetas es que parece muy poco sostenible. Por otro lado, AppendFormat de StringBuilder no solo hace que el código se pueda mantener, sino que también se ejecuta con buena eficacia.

He realizado una ligera mejora en el método # 1 de MattSlay. Utilicé solo una llamada al método AppendFormat de StringBuilder y utilicé el literal de cadena C# para definir el formato. Como resultado, el formato termina pareciéndose exactamente al resultado deseado y se ejecuta con eficiencia.

var sb = new StringBuilder(); 
    sb.AppendFormat(
    @"<div class='control-group'> 
      <label class='control-label' for='{0}_{1}'>{2}</label> 
      <div class='controls'> 
      <input id='{0}_{1}' name='{0}[{1}]' value='{3}' /> 
      </div> 
     </div>", 
     propObj.ModelType, 
     propObj.ModelProperty, 
     propObj.LabelCaption, 
     propObj.PropertyValue); 

    return new HtmlString(sb.ToString()); 

Hope this helps!

+0

era una vieja pregunta. cuál es su propuesta, cambie las clases como 'control-label'. todos están codificados como páginas de asp classico (no asp.net). Siempre pienso que el mantenimiento es más importante que el código. –

+0

Esto no parece funcionar, ya que el valor de la entrada se establecerá en el título de la etiqueta. Tenga en cuenta que la versión de MattSlay utiliza dos listas diferentes de params. Podría deshacerse de las copias de ModelType y ModelProperty y acceder a PropertyValue como {3} – Robert

+0

@Robert. Simplemente estaba tratando de demostrar que podía obtener la eficacia de TagBuilder y el mantenimiento del código mediante el uso de una única llamada al AppendFormat en lugar de múltiples llamadas. para AppendFormat como MattSlay. Además de una sola llamada a AppendFormat, observe cómo C# 's String literal le permite definir la cadena formateada con espacios para su legibilidad. Una vez más, estaba tratando de mejorar el método de MattSlay :) –