2010-09-27 4 views
36

Estoy buscando una forma de escribir el siguiente código con menos líneas de código (quizás 5). Supongo que podría hacer lo mismo que la clase seleccionada, pero esta sintaxis de afeitar no se ve bonita.Cómo crear concisamente atributos HTML opcionales con el motor de vista razorosa?

<ul> 
@foreach (var mi in Model.MenuItems) { 
    <[email protected](mi.Selected?" class=\"selected\"":null)> 
    @if (string.IsNullOrEmpty(mi.Title)) { 
    <a href="@mi.Href">@mi.Text</a> 
    } else { 
    <a href="@mi.Href" title="@mi.Title">@mi.Text</a> 
    } 
    </li> 
} 
</ul> 
+0

La última versión de la maquinilla de afeitar ahora tiene soporte para esto. Ver la respuesta a continuación. – JarrettV

Respuesta

46

fijos en ASP.NET MVC 4

ver http://weblogs.asp.net/jgalloway/archive/2012/02/16/asp-net-4-beta-released.aspx

atributo condicional representación

Si usted tiene un atributo que puede ser nulo, en el pasado se ha necesitado para hacer una verificación nula para evitar escribir un atributo vacío, así:

<div @{if (myClass != null) { <text>class="@myClass"</text> } }>Content</div> 

Ahora Razor puede manejarlo automáticamente, por lo que puede escribir el atributo.Si es nulo, el atributo no está escrito:

<div class="@myClass">Content</div> 

Así que si @myClass es nulo, el resultado es simplemente esto:

<div>Content</div> 
+6

En realidad, no quiere decir ASP.NET 4, quiere decir ASP.NET * MVC * 4 que en el momento de escribir está aún en beta - ASP.NET 4 incluido con VS2010 y .NET 4.0 y no contiene representación de atributos condicional . –

+1

¿Cómo hago eso si quiero agregar un estilo a otros estilos? Di si un bool es verdadero, entonces 'display: none' por ejemplo. ¿O todavía necesito usar ese feo condicional? – ppumkin

+0

¡Buena respuesta, funciona genial! –

9
<ul> 
@foreach (var mi in Model.MenuItems) { 
    <[email protected](mi.Selected?" class=\"selected\"":null)> 
     <a href="@mi.Href" @{if(!string.IsNullOrEmpty(mi.Title)) { <text>title="@mi.Title"</text>} }>@mi.Text</a> 
    </li> 
} 
</ul> 

Yo no lo he probado pero analiza correctamente.

+0

Esto no funciona – JarrettV

+2

Guau, si también se hubiera tomado el tiempo de ver el mensaje de error, habría visto que todo lo que necesitaba hacer era agregar un {} alrededor del contenido del bloque if y habría visto que mi código produce la salida exacta usted estaba buscando ... – Buildstarted

+0

Yikes, "miré" el mensaje de error y probé los corchetes, pero no debo haber comprendido el mensaje. :) Gracias por actualizar tu publicación. – JarrettV

7

Eso sería un buen candidato para el ayudante HTML personalizada:

public static class HtmlExtensions 
{ 
    public static MvcHtmlString MenuItem(this HtmlHelper htmlHelper, MenuItem mi) 
    { 
     var li = new TagBuilder("li"); 
     if (mi.Selected) 
     { 
      li.AddCssClass("selected"); 
     } 
     var a = new TagBuilder("a"); 
     a.MergeAttribute("href", mi.Href); 
     if (!string.IsNullOrEmpty(mi.Title)) 
     { 
      a.MergeAttribute("title", mi.Title); 
     } 
     a.SetInnerText(mi.Text); 
     return MvcHtmlString.Create(li.ToString()); 
    } 
} 

y en su opinión:

<ul> 
@foreach (var mi in Model.MenuItems) { 
    @Html.MenuItem(mi) 
} 
</ul> 

o utilizando DisplayTemplates que ni siquiera necesita para escribir un bucle:

<ul> 
    @Html.DisplayFor(x => x.MenuItems) 
</ul> 
+0

Darin, su código es genial, pero de alguna manera siento que esto está derrotando el propósito de la afeitadora. Microsoft necesita abordar esto. – JarrettV

40

He creado una clase de HtmlAttribute encadenable y algunos métodos de extensión Html para permitir el Razo sintaxis r a continuación:

<ul> 
    @foreach (var mi in items) { 
    <li @Html.Css("selected", mi.Selected)> 
     <a href="@mi.Href" @Html.Attr("title", mi.Title)>@mi.Text</a> 
    </li> 
    } 
</ul> 

Aquí está la clase HtmlAttribute:

public class HtmlAttribute : IHtmlString  
{ 
    private string _InternalValue = String.Empty; 
    private string _Seperator; 

    public string Name { get; set; } 
    public string Value { get; set; } 
    public bool Condition { get; set; } 

    public HtmlAttribute(string name) 
     : this(name, null) 
    { 
    } 

    public HtmlAttribute(string name, string seperator) 
    { 
     Name = name; 
     _Seperator = seperator ?? " "; 
    } 

    public HtmlAttribute Add(string value) 
    { 
     return Add(value, true); 
    } 

    public HtmlAttribute Add(string value, bool condition) 
    { 
     if (!String.IsNullOrWhiteSpace(value) && condition) 
      _InternalValue += value + _Seperator; 

     return this; 
    } 

    public string ToHtmlString() 
    { 
     if (!String.IsNullOrWhiteSpace(_InternalValue)) 
      _InternalValue = String.Format("{0}=\"{1}\"", Name, _InternalValue.Substring(0, _InternalValue.Length - _Seperator.Length)); 
     return _InternalValue; 
    } 
} 

Información adicional: El "separador" se utiliza para encadenar varios valores para un atributo. Esto puede ser útil para múltiples nombres de clase css (use un espacio) o tal vez use String.Empty para construir un valor que dependa de múltiples condiciones (usando el método .Add())

Y aquí están los métodos de ayuda de la extensión Html :

public static class Extensions 
{ 
    public static HtmlAttribute Css(this HtmlHelper html, string value) 
    { 
     return Css(html, value, true); 
    } 

    public static HtmlAttribute Css(this HtmlHelper html, string value, bool condition) 
    { 
     return Css(html, null, value, condition); 
    } 

    public static HtmlAttribute Css(this HtmlHelper html, string seperator, string value, bool condition) 
    { 
     return new HtmlAttribute("class", seperator).Add(value, condition); 
    } 

    public static HtmlAttribute Attr(this HtmlHelper html, string name, string value) 
    { 
     return Attr(html, name, value, true); 
    } 

    public static HtmlAttribute Attr(this HtmlHelper html, string name, string value, bool condition) 
    { 
     return Attr(html, name, null, value, condition); 
    } 

    public static HtmlAttribute Attr(this HtmlHelper html, string name, string seperator, string value, bool condition) 
    { 
     return new HtmlAttribute(name, seperator).Add(value, condition); 
    } 
} 

Avísame si son útiles.

Gracias,

Lee

+1

Necesita escaparse de los valores. – SLaks

+0

Hola Lee, ¿puedes darme una pista sobre dónde colocar estas clases en un proyecto de MVC y cómo/dónde hacer referencia a ellas? –

4
<ul> 
@foreach (var mi in Model.MenuItems) { 
    <[email protected](Html.Raw((mi.Selected ? " class=\"selected\"" : null))> 
    <a href="@mi.Href">@mi.Text</a> 
    </li> 
} 
</ul> 
-1

Es realmente muy sencillo y limpio:

<p @(cssClass != null) ? { class="@cssClass" }> Stuff and whatnot... </p> 
+3

Esto no es válido. –

2

class atributo no quedaría por Razor si el valor es null

<a href="#nolink" class="@(categoryId == null ? "submenu-active": null)">All</a> 
1

Para el caso de múltiples clases utilizo este sencillo método de extensión:

public static MvcHtmlString If(this string text, bool condition) { 
    return new MvcHtmlString(condition ? text : string.Empty); 
} 

Y en la vista:

<div class="menuitem @("active".If(Model.Active))"> 
Cuestiones relacionadas