2010-03-23 10 views
19

Al usar un HTML Helper, ¿cuál es el mejor método para establecer un atributo basado en una condición. Por ejemploCómo configurar deshabilitado en MVC htmlAttribute

<%if (Page.User.IsInRole("administrator")) {%> 
<%=Html.TextBoxFor(m => m.FirstName, new {@class='contactDetails'}%> 
<%} else {%> 
<%=Html.TextBoxFor(m => m.FirstName, new {@class='contactDetails', disabled = true}%> 
<%}%> 

Tiene que haber una mejor manera de añadir sólo un par de claves mediante programación adicional al tipo anónimo? No se puede usar

new { .... disabled = Page.User.IsInRole("administrator") ... } 

como el navegador toma cualquier valor de atributo discapacitados como hacer la entrada deshabilitado

+0

¿Cuál es el error que está obteniendo? 'Page.User.IsInRole (...)' no funciona? –

+0

Ningún error, solo tratando de reducir la cantidad de código duplicado – Ollie

+0

http://stackoverflow.com/a/10207597/155899 – nfplee

Respuesta

14

Podría sugerirle que use mvccontrib.FluentHtml.

Puede hacer algo como esto

<%=this.TextBox(m=>m.FirstNam).Disabled(Page.User.IsInRole("administrator"))%> 
+0

Guau, eso es bonito. ¡Definitivamente lo comprobé este fin de semana! –

2

Tendrá que pasar una Dictionary<string, object>, y añadir la clave disabled dentro de una sentencia if.

Recomiendo hacer una sobrecarga del método de extensión que toma un parámetro bool disabled y lo agrega a un RouteValueDictionary creado a partir del parámetro de atributos si es true. (También podría eliminar la entrada disabled del RouteValueDictionary si es false, y no tomar otro parámetro)

+0

Si lo hace, seguirá representando un atributo "deshabilitado" y la mayoría de los navegadores lo considerarán como deshabilitado independientemente de disabled = "disabled" – hunter

+0

Entonces necesitarás usar un diccionario. – SLaks

8

Page.User.IsInRole ("administrador")? null: {nueva discapacitados = "desactivado"}

+2

+1 Buena idea ... (A menos que necesite otros atributos) – SLaks

+1

Necesito otros atributos, la repetición de código es lo que trato de evitar – Ollie

0

También puede definir este parámetro de esa manera:

Page.User.IsInRole("administrator") 
    ? (object)new { @class='contactDetails'} 
    : (object)new { @class='contactDetails', disabled = true} 
+0

Es la repetición de código que trato de evitar, cuando tienes muchos atributos esto se vuelve tan complicado – Ollie

+0

No estoy seguro de que realmente me guste la legibilidad de él también, pero cuando se usan tipos anónimos, debe crear varias instancias para cada conjunto de atributos. –

4

Usando @SLaks sugerencia de utilizar un método de extensión, y el uso de Jeremiah Clark's example Extension method He escrito un método de extensión así que ahora puedo hacer

Html.TextBoxFor(m => m.FirstName,new{class='contactDetails', ...},Page.User.IsInRole("administrator")); 

No estoy seguro si hay un método mejor, aunque

public static class InputExtensions 
{ 

    public static IDictionary<string, object> TurnObjectIntoDictionary(object data) 
    { 
     var attr = BindingFlags.Public | BindingFlags.Instance; 
     var dict = new Dictionary<string, object>(); 
     if (data == null) 
      return dict; 
     foreach (var property in data.GetType().GetProperties(attr)) 
     { 
      if (property.CanRead) 
      { 
       dict.Add(property.Name, property.GetValue(data, null)); 
      } 
     } 
     return dict; 

    } 

    public static MvcHtmlString TextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, bool disabled) 
    { 
     IDictionary<string, object> values = TurnObjectIntoDictionary(htmlAttributes); 

     if (disabled) 
      values.Add("disabled","true"); 


     return htmlHelper.TextBoxFor(expression, values); 
    } 

    public static MvcHtmlString TextAreaFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, bool disabled) 
    { 
     IDictionary<string, object> values = TurnObjectIntoDictionary(htmlAttributes); 

     if (disabled) 
      values.Add("disabled", "true"); 


     return htmlHelper.TextAreaFor(expression, values); 
    } 

    public static MvcHtmlString CheckBoxFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool>> expression, object htmlAttributes, bool disabled) 
    { 
     IDictionary<string, object> values = TurnObjectIntoDictionary(htmlAttributes); 

     if (disabled) 
      values.Add("disabled", "true"); 


     return htmlHelper.CheckBoxFor(expression, values); 
    } 
} 
+0

Debe reemplazar su método 'TurnObjectIntoDictionary' con un' RouteValueDictionary', que es lo que usan todos los métodos de extensión. Debería ser más rápido. Además, debes aceptar mi respuesta. – SLaks

+0

BTW, cualquiera que intente esto necesitará 'usar System.Web.Mvc' y 'usando System.Web.Mvc.Html' – rohancragg

+0

FYI, ahora puede usar la función 'HtmlHelper.AnonymousObjectToHtmlAttributes (htmlAttributes)', que devuelve un ' RouteValueDictionary'. La razón por la que tuve que usar esta función, en lugar de 'TurnObjectIntoDictionary (htmlAttributes)' es que 'TurnObjectIntoDictionary' no estaba convirtiendo propiedades como' data_bind = "foo" 'to' data-bind = "foo" 'en el HTML generado. –

1

Es posible que desee considerar la escritura de su propia clase HtmlHelper de extensión con un nuevo método Cuadro de texto:

public static class HtmlHelperExtensions 
{ 
    public static MvcHtmlString TextBoxFor(this HtmlHelper htmlHelper, Expression<Func<TModel, TProperty>> expression, string cssClass, bool disabled) 
    { 
     return disabled 
      ? Html.TextBoxFor(expression, new {@class=cssClass, disabled="disabled"}) 
      : Html.TextBoxFor(expression, new {@class=cssClass}) 
    } 
} 

ahora (si esta nueva clase se encuentra en el mismo espacio de nombres, o que haya importado el nuevo espacio de nombres para el encabezado de la página o en la sección de las páginas del web.config) se puede hacer esto en su página aspx:

<%=Html.TextBoxFor(m => m.FirstName, "contactDetails", Page.User.IsInRole("administrator")) %> 
1

Creado un método de extensión en el objeto que va a crear una copia del objeto de entrada con exclusión de cualesquiera propiedades que son nulas, y devolverlo todo como un diccionario que lo hace fácilmente utilizado en MVC HtmlHelpers:

public static Dictionary<string, object> StripAnonymousNulls(this object attributes) 
{ 
    var ret = new Dictionary<string, object>(); 
    foreach (var prop in attributes.GetType().GetProperties()) 
    { 
     var val = prop.GetValue(attributes, null); 
     if (val != null) 
     ret.Add(prop.Name, val); 
    } 
    return ret; 
} 

No está seguro acerca de implicaciones de rendimiento que refleja a través de propiedades en dos ocasiones, y no les gusta el nombre del método de extensión mucho, pero parece que para hacer bien el trabajo ...

new { 
     @class = "contactDetails", 
     disabled = Page.User.IsInRole("administrator") ? "true" : null 
    }.StripAnonymousNulls() 
12

Funciona para mí también...

<%: Html.DropDownList("SportID", (SelectList)ViewData["SportsSelectList"], "-- Select --", new { @disabled = "disabled", @readonly = "readonly" })%> 

<%= Html.CheckBoxFor(model => model.IsActive, new { @disabled = "disabled", @readonly = "readonly" })%> 
Cuestiones relacionadas