2011-04-11 8 views
48

Tengo una ActionStatus Llamado Enum que tiene 2 valores posibles abiertas = 0 y cerrado = 1pase enumeración de html.radiobuttonfor MVC3

public enum ActionStatus 
{ 
    Open, 
    Closed 
} 

Quiero construir grupo de botones de radio en mi editar y crear vistas que utiliza la enumeración para rellenar los botones de opción con a) un valor predeterminado en la vista de creación yb) la opción actualmente seleccionada en la vista de edición.

¿Necesito un método de extensión para esto, y alguien ya ha creado uno?

EDIT: Después de la respuesta de Darins por debajo de este es mi clase de modelo

namespace Actioner.Models 
{ 
[MetadataType(typeof(MeetingActionValidation))] 
public class MeetingAction 
{ 
    [Key] 
    public int MeetingActionId    { get; set; }  

    [Required] 
    [Display(Name = "Description")] 
    public string Description { get; set; } 

    [Required] 
    [Display(Name = "Review Date")] 
    public DateTime ReviewDate  { get ;set; } 

    public int Status{ get; set; } 

    [ScaffoldColumn(false)] 
    public int MeetingId    { get; set; } 


    //public virtual Meeting Meeting { get; set; } 

    //public virtual ICollection<User> Users { get; set; } 
    public virtual ICollection<ActionUpdate> ActionUpdates { get; set; } 

    public MeetingActionStatus ActionStatus { get; set; } 

} 

public enum MeetingActionStatus 
{ 
    Open, 
    Closed 
} 

y este es mi punto de vista

@model Actioner.Models.MeetingAction 
@using Actioner.Helpers 


<div class="editor-label"> 
@Html.LabelFor(model => model.Description) 
</div> 
<div class="editor-field"> 
@Html.EditorFor(model => model.Description) 
@Html.ValidationMessageFor(model => model.Description) 
</div> 

<div class="editor-label"> 
@Html.LabelFor(model => model.ReviewDate) 
</div> 
<div class="editor-field"> 
@Html.EditorFor(model => model.ReviewDate) 
@Html.ValidationMessageFor(model => model.ReviewDate) 
</div> 

<div class="editor-label"> 
@Html.LabelFor(model => model.Status) 
</div> 
<div class="editor-field"> 

@Html.RadioButtonForEnum(x => x.ActionStatus) 

</div> 

Y esta es mi creación acción del controlador

public virtual ActionResult Create(int id) 
    { 

     var meetingAction = new MeetingAction 
     { 
      MeetingId = id, 
      ReviewDate = DateTime.Now.AddDays(7) 
     }; 

     ViewBag.Title = "Create Action"; 

     return View(meetingAction); 
    } 

La enumeración se muestra bien en la vista, pero la opción seleccionada no se conserva en la base de datos

+0

¿Hay alguna manera es posible recuperar del archivo de recursos para Open y valores cercanos? Ej: [Pantalla (Nombre = "Abrir", ResourceType = typeof (Resources.Global), Order = 0)] Abrir. –

Respuesta

79
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Text; 
using System.Web; 
using System.Web.Mvc; 
using System.Web.Mvc.Html; 

namespace YourNamespace 
{ 
    public static class HtmlExtensions 
    { 
     public static MvcHtmlString RadioButtonForEnum<TModel, TProperty>(
      this HtmlHelper<TModel> htmlHelper, 
      Expression<Func<TModel, TProperty>> expression 
     ) 
     { 
      var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); 
      var names = Enum.GetNames(metaData.ModelType); 
      var sb = new StringBuilder(); 
      foreach (var name in names) 
      { 
       var id = string.Format(
        "{0}_{1}_{2}", 
        htmlHelper.ViewData.TemplateInfo.HtmlFieldPrefix, 
        metaData.PropertyName, 
        name 
       ); 

       var radio = htmlHelper.RadioButtonFor(expression, name, new { id = id }).ToHtmlString(); 
       sb.AppendFormat(
        "<label for=\"{0}\">{1}</label> {2}", 
        id, 
        HttpUtility.HtmlEncode(name), 
        radio 
       ); 
      } 
      return MvcHtmlString.Create(sb.ToString()); 
     } 
    } 
}  

También puede forzar un generic constraint to an enum type para este método de ayuda.

y luego:

Modelo:

public enum ActionStatus 
{ 
    Open, 
    Closed 
} 

public class MyViewModel 
{ 
    public ActionStatus Status { get; set; } 
} 

controlador:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     return View(new MyViewModel 
     { 
      Status = ActionStatus.Closed 
     }); 
    } 

    [HttpPost] 
    public ActionResult Index(MyViewModel model) 
    { 
     return View(model); 
    } 
} 

Ver:

@model MyViewModel 
@using (Html.BeginForm()) 
{ 
    @Html.RadioButtonForEnum(x => x.Status) 
    <input type="submit" value="OK" /> 
} 
+0

¿Por qué usas un generador de cadenas? ¿Solo por la facilidad de concatenación y formateo? Parece una forma muy poco MVC de hacer cosas. –

+1

El enlace al blog de Jon Skeet sobre la aplicación de una restricción genérica a un tipo de enumeración ya no funciona. –

+1

Tardó unos minutos en encontrar las declaraciones correctas de 'uso' para usar para el código HtmlExtensions, así que edité su respuesta para incluirlas. Espero que no te importe. –

10

Sólo tiene que añadir etiquetas de los botones de radio

public static class HtmlExtensions 
{ 
    public static MvcHtmlString RadioButtonForEnum<TModel, TProperty>(
     this HtmlHelper<TModel> htmlHelper, 
     Expression<Func<TModel, TProperty>> expression 
    ) 
    { 
     var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); 

     var names = Enum.GetNames(metaData.ModelType); 
     var sb = new StringBuilder(); 
     foreach (var name in names) 
     { 

      var description = name; 

      var memInfo = metaData.ModelType.GetMember(name); 
      if (memInfo != null) 
      { 
       var attributes = memInfo[0].GetCustomAttributes(typeof(DisplayAttribute), false); 
       if (attributes != null && attributes.Length > 0) 
        description = ((DisplayAttribute)attributes[0]).Name; 
      } 
      var id = string.Format(
       "{0}_{1}_{2}", 
       htmlHelper.ViewData.TemplateInfo.HtmlFieldPrefix, 
       metaData.PropertyName, 
       name 
      ); 

      var radio = htmlHelper.RadioButtonFor(expression, name, new { id = id }).ToHtmlString(); 
      sb.AppendFormat(
       "<label for=\"{0}\">{1}</label> {2}", 
       id, 
       HttpUtility.HtmlEncode(description), 
       radio 
      ); 
     } 
     return MvcHtmlString.Create(sb.ToString()); 
    } 
} 

y el Modelo:

public enum MeetingActionStatus     
{ 

    [Display(Name = "Open meeting")] 
    Open, 

    [Display(Name = "Closed meeting")] 
    Closed    
}   
+1

El uso de en el modelo y en la extensión del atributo 'Pantalla' es bastante útil ya que muchas veces la descripción de las enumeraciones no se puede utilizar para mostrar realmente en su formato sin formato. – atconway

+0

Recibo un error - 'System.Web.Mvc.HtmlHelper ' no contiene una definición para 'RadioButtonFor' y ningún método de extensión 'RadioButtonFor' que acepta un primer argumento de tipo 'System.Web.Mvc.HtmlHelper ' – Neil

+1

Intenta "usar System.Web.Mvc.Html;" – Jack