2012-06-26 19 views
12

Mañana todos.MVC 4, lista de casilla de verificación y yo

Veo que esto se ha discutido en otro lado pero me preguntaba si algo había cambiado o si las cosas se simplificaron en MVC 4 para simplones como yo?

Escenario

que tiene la siguiente, editado, modelo:

public class CorporateDetails 
{ 

    public Guid? Id { get; set; } 

    [Key] 
    public int CorporateDetailId { get; set; } 

    public int? EmsId { get; set; } 
    public string EmsName { get; set; } 

    public virtual EmsType EmsType { get; set; } 
} 

public class EmsType 
{ 
    [Key] 
    public int? EmsId { get; set; } 
    public string EmsName { get; set; } 

    public virtual ICollection<EmsType> EmsTypes { get; set; } 
} 

Con el siguiente estándar crear vista:

<fieldset> 
    <legend>CorporateDetails</legend> 



    <div class="editor-label"> 
     @Html.LabelFor(model => model.EmsId, "EmsType") 
    </div> 
    <div class="editor-field"> 
     @Html.DropDownList("EmsId", String.Empty) 
     @Html.ValidationMessageFor(model => model.EmsId) 
    </div> 
    <div class="editor-label"> 
     @Html.LabelFor(model => model.EmsName) 
    </div> 
    <div class="editor-field"> 
     @Html.EditorFor(model => model.EmsName) 
     @Html.ValidationMessageFor(model => model.EmsName) 
    </div> 

    <p> 
     <input type="submit" value="Create" /> 
    </p> 
</fieldset> 

Esto me da, fuera de la caja, una hermosa ventana desplegable n list a la Scott Gu's blog

Ahora mi verdadera pregunta es esta: ¿cómo puedo convertir de forma efectiva este cuadro desplegable a lo que efectivamente será una selección múltiple, casilla de verificación?

Una vez más, me disculpo por haber pisado tierra pisoteada pero solo estaba probando el agua para ver si ha habido alguna actualización.

Tenga en cuenta, el primer proyecto MVC así que ir con cuidado, me siento muy gruesa de nuevo: '(

Respuesta

19

Bien, bien, lo tengo ordenado - ¡hurra! Como se puede ver en los comentarios, hay algunos problemas que surgieron, pero a continuación les presentamos la solución completa, que hace el trabajo: D

Modelo

public class CorporateDetails 
    { 

     public Guid? Id { get; set; } 

     [Key] 
     public int CorporateDetailId { get; set; } 

     public int[] EmsId { get; set; } 

     } 

    public class EmsType 
    { 
     [Key] 
     public int EmsId { get; set; } 
     public string EmsName { get; set; } 

     public virtual ICollection<EmsType> EmsTypes { get; set; } 
    } 

controlador

public ActionResult Create() 
    { 
     CorporateDetails corporatedetails = new CorporateDetails(); 
     ViewBag.EmsId = new MultiSelectList(db.EmsTypes, "EmsId", "EmsName"); 
     return View(corporatedetails); 
    } 

Extensión (ubicado en una carpeta en la raíz del proyecto)

public static MvcHtmlString CheckBoxListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty[]>> expression, MultiSelectList multiSelectList, object htmlAttributes = null) 
    { 
     //Derive property name for checkbox name 
     MemberExpression body = expression.Body as MemberExpression; 
     string propertyName = body.Member.Name; 

     //Get currently select values from the ViewData model 
     TProperty[] list = expression.Compile().Invoke(htmlHelper.ViewData.Model); 

     //Convert selected value list to a List<string> for easy manipulation 
     List<string> selectedValues = new List<string>(); 

     if (list != null) 
     { 
      selectedValues = new List<TProperty>(list).ConvertAll<string>(delegate(TProperty i) { return i.ToString(); }); 
     } 

     //Create div 
     TagBuilder divTag = new TagBuilder("div"); 
     divTag.MergeAttributes(new RouteValueDictionary(htmlAttributes), true); 

     //Add checkboxes 
     foreach (SelectListItem item in multiSelectList) 
     { 
      divTag.InnerHtml += String.Format("<div><input type=\"checkbox\" name=\"{0}\" id=\"{0}_{1}\" " + 
               "value=\"{1}\" {2} /><label for=\"{0}_{1}\">{3}</label></div>", 
               propertyName, 
               item.Value, 
               selectedValues.Contains(item.Value) ? "checked=\"checked\"" : "", 
               item.Text); 
     } 

     return MvcHtmlString.Create(divTag.ToString()); 
    } 

extensión registrada en web.config de las Vistas

<pages pageBaseType="System.Web.Mvc.WebViewPage"> 
    <namespaces> 
    <add namespace="System.Web.Mvc" /> 
    <add namespace="System.Web.Mvc.Ajax" /> 
    <add namespace="System.Web.Mvc.Html" /> 
    <add namespace="System.Web.Optimization"/> 
    <add namespace="System.Web.Routing" /> 
    <add namespace="MyProject.Extensions" /> 
    </namespaces> 
</pages> 

Ver

@model Valpak.Websites.HealthChecker.Models.CorporateDetails 
@{ 
    ViewBag.Title = "Create"; 
} 
<h2>Create</h2> 
@using (Html.BeginForm()) 
{ 
    @Html.ValidationSummary(true) 

    <fieldset> 
     <legend>CorporateDetails</legend> 

      <div class="editor-label"> 
      @Html.CheckBoxListFor(model => model.EmsId, (MultiSelectList) ViewBag.EmsId) 
      </div>   
     <p> 
      <input type="submit" value="Create" /> 
     </p> 
    </fieldset> 
} 
<div> 
    @Html.ActionLink("Back to List", "Index") 
</div> 
@section Scripts { 
    @Scripts.Render("~/bundles/jqueryval") 
} 

Lo que me da una lista de casillas de verificación preciosa. ¡Hurra!

Gracias Darin por su ayuda, he marcado esto como la respuesta, pero +50 por su tiempo y esfuerzo.

+0

Realmente útil, pero sería incluso mejor si se incluyera la validación. Actualmente, todos mis cuadros de texto tienen un borde rojo si hay un problema de validación, ¿tienes alguna idea de cómo incluir esa función? – Owen

2

no se produjeron cambios en ASP.NET MVC 4 RC en este aspecto y es poco probable que ocurra cuando llega a RTM .

Pero todavía implement a custom helper podría lograr eso. Y se podría incluso mejorar esta ayuda para que tome una expresión lambda como primer argumento en lugar de una cadena con el fin de tener la versión inflexible.

Y si no están utilizando enumeraciones aquí es another example.

+0

Gracias Darin - con el exmaple extensión, debe acabo de añadir que como en cualquier lugar de mi proyecto o específicamente con las vistas? (Disculpas por la estúpida pregunta, vea la nota al pie del "primer proyecto MVC") –

+0

Puede crear una carpeta 'Extensions' y tener una clase' HtmlExtensions.cs' dentro de la cual las declarará. –

+0

Eso tendría sentido: D Lo sentimos –

1

Si pasa el valor seleccionado para MultiSelected (parámetro # 4)

ViewBag.VfonctionIds = new MultiSelectList(db.tbIntervenantFonctionTypes, "intervenantFonctionType_id", "Nom", fonctionSelected); 

Cambiar el ayudante de

 public static MvcHtmlString CheckBoxListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty[]>> expression, MultiSelectList multiSelectList, object htmlAttributes = null) 
    { 
     //Derive property name for checkbox name 
     MemberExpression body = expression.Body as MemberExpression; 
     string propertyName = body.Member.Name; 

     //Create div 
     TagBuilder divTag = new TagBuilder("div"); 
     divTag.MergeAttributes(new RouteValueDictionary(htmlAttributes), true); 

     //Add checkboxes 
     foreach (SelectListItem item in multiSelectList) 
     { 
      divTag.InnerHtml += String.Format("<div><input type=\"checkbox\" name=\"{0}\" id=\"{0}_{1}\" " + 
               "value=\"{1}\" {2} /><label for=\"{0}_{1}\">{3}</label></div>", 
               propertyName, 
               item.Value, 
               (item.Selected) ? "checked=\"checked\"" : "",              
               item.Text); 
     } 

     return MvcHtmlString.Create(divTag.ToString()); 
    } 
Cuestiones relacionadas