2012-09-28 27 views
8

Estoy tratando de crear un HtmlHelper y necesito permitir a los usuarios agregar sus propios atributos personalizados a la etiqueta html.TagBuilder.MergeAttributes no funciona como se esperaba

Intenté hacer esto usando la clase TagBuilder, pero parece que en lugar de fusionar los atributos, simplemente los reemplaza.

Esto es lo que hice en C#:

public static MvcHtmlString List(HtmlHelper helper, object htmlAttributes) 
{ 
    var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); 

    var tag = new TagBuilder("div"); 
    tag.AddCssClass("myClass"); 
    tag.MergeAttributes(attributes, false); 

    // tag class property has value "myClass", not "myClass testClass" 

    return new MvcHtmlString("<div>"); 
} 

Este es mi punto de vista:

@Html.List(new { @class = "testClass" }) 

¿Qué estoy haciendo mal?

+0

Pregunta similar respondida por Darin Dimitrov. http://stackoverflow.com/questions/9519951/using-htmlattributes-for-inserting-an-additional-class-to-my-link-on-my-helper –

Respuesta

16

El método TagBuilder.MergeAttributes no funciona como esperabas. Este es el código exacto de este método:

public void MergeAttributes<TKey, TValue>(IDictionary<TKey, TValue> attributes, bool replaceExisting) 
    { 
     if (attributes != null) 
     { 
      foreach (var entry in attributes) 
      { 
       string key = Convert.ToString(entry.Key, CultureInfo.InvariantCulture); 
       string value = Convert.ToString(entry.Value, CultureInfo.InvariantCulture); 
       MergeAttribute(key, value, replaceExisting); 
      } 
     } 
    } 

    public void MergeAttribute(string key, string value, bool replaceExisting) 
    { 
     if (String.IsNullOrEmpty(key)) 
     { 
      throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "key"); 
     } 

     if (replaceExisting || !Attributes.ContainsKey(key)) 
     { 
      Attributes[key] = value; 
     } 
    } 

Como se puede ver sólo añade nuevos atributos a la colección (si replaceExisting se establece en true también reemplaza los ya en la colección). No realiza y atribuye valores que combinan lógica. Si desea combinar los valores que hay que hacer por ti mismo:

public static MvcHtmlString List(this HtmlHelperhelper, object htmlAttributes) 
{ 
    var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);   
    if (attributes.ContainsKey("class")) 
     attributes["class"] = "myclass " + attributes["class"]; 
    else 
     attributes.Add("class", "myClass"); 

    var tag = new TagBuilder("div"); 
    tag.MergeAttributes(attributes, false); 

    return new MvcHtmlString(tag.ToString(TagRenderMode.Normal)); 
} 
+1

Véase mi respuesta, es sólo un caso de utilizar los dos métodos en el orden incorrecto – Darren

25

El MergeAttributes anula los atributos que ya están en la etiqueta, AddCssClass anexa el nombre en el valor de la clase.

Así que simplemente enciéndalo y funcionará;

tag.MergeAttributes(attributes, false); 
    tag.AddCssClass("myClass"); 

AddCssClass se agregará a los nombres de clase fusionados arriba.

+1

Esta es la respuesta correcta y debería ser la respuesta aceptada –

4

Necesitaba combinar otros atributos (además de la clase), por lo que AddCssClass() no era suficiente. Escribí un método de extensión para hacer lo que creía que MergeAttributes debía hacer:

public static class TagBuilderExtensions 
{ 
    public static void TrueMergeAttributes(this TagBuilder tagBuilder, IDictionary<string, object> attributes) 
    { 
     foreach (var attribute in attributes) 
     { 
      string currentValue; 
      string newValue = attribute.Value.ToString(); 

      if (tagBuilder.Attributes.TryGetValue(attribute.Key, out currentValue)) 
      { 
       newValue = currentValue + " " + newValue; 
      } 

      tagBuilder.Attributes[attribute.Key] = newValue; 
     } 
    } 
} 
+0

Esta lógica probablemente no funcionará como debería si necesita fusionar/anular cualquier otra cosa que no sean clases. – Sinjai

Cuestiones relacionadas