2010-08-12 5 views
6

Estoy trabajando en una página donde el usuario necesita completar información y finalmente hacer una selección de 1 o más clientes con casillas de verificación. El número de clientes es IEnumerable<Customer> que paso a mi Modelo. ¿Cómo voy a crear la lista de casillas de verificación usando .CheckBoxFor()?Cómo usar Html.CheckBox (lista) con IEnumerable <T> con validación

Y finalmente me gustaría poder validar si se ha seleccionado al menos 1 casilla de verificación.

La solicitud es el objeto que contiene la información que el usuario ingresó.

<% foreach (var customer in Model.Request.Customers) { %> 
    <%= Html.CheckBoxFor(/* customer */) %> 
<% } %> 

¿Alguien puede señalarme en la dirección correcta? ¿O estoy haciendo esto mal?

Respuesta

3

Puede crear una clase personalizada de extensiones html y sobrecargar el método CheckBoxFor como se muestra a continuación. El método evalúa los metadatos.Modelo del valor pasado a él (como Estado de EE. UU.). Usted puede obtener el valor de la casilla/s de la FormCollection en el ControllerAction:

public ActionResult Edit(FormCollection formCollection) 
{ 
    // Get the value(s) 
    string checkBox = formCollection["State"]; 

    // perform validation 
    .... 
} 

este caso se hace una lista genérica KeyValuePair

<% foreach (var element in UnitedStatesDictionary()) 
{ %> 
<%= Html.CheckBoxFor(model => model.State, null, element.Key) %><%= element.Value %><br /> 
<% } %> 

HtmlExtensions.cs

using System; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Web.Mvc; 
using System.Web.Routing; 

    public static class HtmlExtensions 
    { 
     /// <summary> 
     /// Checks the box for. 
     /// </summary> 
     /// <typeparam name="TModel">The type of the model.</typeparam> 
     /// <typeparam name="TValue">The type of the value.</typeparam> 
     /// <param name="html">The HTML.</param> 
     /// <param name="expression">The expression.</param> 
     /// <returns>Checkbox</returns> 
     public static MvcHtmlString CheckBoxFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) 
     { 
      return CheckBoxFor(html, expression, new RouteDirection()); 
     } 


     /// <summary> 
     /// Checks the box for. 
     /// </summary> 
     /// <typeparam name="TModel">The type of the model.</typeparam> 
     /// <typeparam name="TValue">The type of the value.</typeparam> 
     /// <param name="html">The HTML.</param> 
     /// <param name="expression">The expression.</param> 
     /// <param name="htmlAttributes">The HTML attributes.</param> 
     /// <returns>Checkbox</returns> 
     public static MvcHtmlString CheckBoxFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes) 
     { 

      return CheckBoxFor(html, expression, htmlAttributes, ""); 
     } 

     /// <summary> 
     /// Checks the box for. 
     /// </summary> 
     /// <typeparam name="TModel">The type of the model.</typeparam> 
     /// <typeparam name="TValue">The type of the value.</typeparam> 
     /// <param name="html">The HTML.</param> 
     /// <param name="expression">The expression.</param> 
     /// <param name="htmlAttributes">The HTML attributes.</param> 
     /// <param name="checkedValue">The checked value.</param> 
     /// <returns>Checkbox</returns> 
     public static MvcHtmlString CheckBoxFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, object htmlAttributes, string checkedValue) 
     { 

      ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData); 
      string htmlFieldName = ExpressionHelper.GetExpressionText(expression); 

      TagBuilder tag = new TagBuilder("input"); 
      tag.Attributes.Add("type", "checkbox"); 
      tag.Attributes.Add("name", metadata.PropertyName); 
      if (!string.IsNullOrEmpty(checkedValue)) 
      { 
       tag.Attributes.Add("value", checkedValue); 
      } 
      else 
      { 
       tag.Attributes.Add("value", metadata.Model.ToString()); 
      } 

      if (htmlAttributes != null) 
      { 
       tag.MergeAttributes(new RouteValueDictionary(htmlAttributes)); 
      } 

      if (metadata.Model.ToString() == checkedValue) 
      { 
       tag.Attributes.Add("checked", "checked"); 
      } 
      return MvcHtmlString.Create(tag.ToString(TagRenderMode.SelfClosing)); 
     } 
    } 

Mientras estoy en esto, aquí está mi lista de Estados Unidos para completar el código:

/// <summary> 
/// United States dictionary. 
/// </summary> 
/// <returns>List of United States</returns> 
public static List<KeyValuePair<string, string>> UnitedStatesDictionary() 
{ 
    var arrList = new List<KeyValuePair<string, string>>(); 
    arrList.Add(new KeyValuePair<string, string>("AL", "Alabama")); 
    arrList.Add(new KeyValuePair<string, string>("AK", "Alaska")); 
    arrList.Add(new KeyValuePair<string, string>("AZ", "Arizona")); 
    arrList.Add(new KeyValuePair<string, string>("AR", "Arkansas")); 
    arrList.Add(new KeyValuePair<string, string>("CA", "California")); 
    arrList.Add(new KeyValuePair<string, string>("CO", "Colorado")); 
    arrList.Add(new KeyValuePair<string, string>("CT", "Connecticut")); 
    arrList.Add(new KeyValuePair<string, string>("DE", "Delaware")); 
    arrList.Add(new KeyValuePair<string, string>("DC", "District Of Columbia")); 
    arrList.Add(new KeyValuePair<string, string>("FL", "Florida")); 
    arrList.Add(new KeyValuePair<string, string>("GA", "Georgia")); 
    arrList.Add(new KeyValuePair<string, string>("HI", "Hawaii")); 
    arrList.Add(new KeyValuePair<string, string>("ID", "Idaho")); 
    arrList.Add(new KeyValuePair<string, string>("IL", "Illinois")); 
    arrList.Add(new KeyValuePair<string, string>("IN", "Indiana")); 
    arrList.Add(new KeyValuePair<string, string>("IA", "Iowa")); 
    arrList.Add(new KeyValuePair<string, string>("KS", "Kansas")); 
    arrList.Add(new KeyValuePair<string, string>("KY", "Kentucky")); 
    arrList.Add(new KeyValuePair<string, string>("LA", "Louisiana")); 
    arrList.Add(new KeyValuePair<string, string>("ME", "Maine")); 
    arrList.Add(new KeyValuePair<string, string>("MD", "Maryland")); 
    arrList.Add(new KeyValuePair<string, string>("MA", "Massachusetts")); 
    arrList.Add(new KeyValuePair<string, string>("MI", "Michigan")); 
    arrList.Add(new KeyValuePair<string, string>("MN", "Minnesota")); 
    arrList.Add(new KeyValuePair<string, string>("MS", "Mississippi")); 
    arrList.Add(new KeyValuePair<string, string>("MO", "Missouri")); 
    arrList.Add(new KeyValuePair<string, string>("MT", "Montana")); 
    arrList.Add(new KeyValuePair<string, string>("NE", "Nebraska")); 
    arrList.Add(new KeyValuePair<string, string>("NV", "Nevada")); 
    arrList.Add(new KeyValuePair<string, string>("NH", "New Hampshire")); 
    arrList.Add(new KeyValuePair<string, string>("NJ", "New Jersey")); 
    arrList.Add(new KeyValuePair<string, string>("NM", "New Mexico")); 
    arrList.Add(new KeyValuePair<string, string>("NY", "New York")); 
    arrList.Add(new KeyValuePair<string, string>("NC", "North Carolina")); 
    arrList.Add(new KeyValuePair<string, string>("ND", "North Dakota")); 
    arrList.Add(new KeyValuePair<string, string>("OH", "Ohio")); 
    arrList.Add(new KeyValuePair<string, string>("OK", "Oklahoma")); 
    arrList.Add(new KeyValuePair<string, string>("OR", "Oregon")); 
    arrList.Add(new KeyValuePair<string, string>("PA", "Pennsylvania")); 
    arrList.Add(new KeyValuePair<string, string>("RI", "Rhode Island")); 
    arrList.Add(new KeyValuePair<string, string>("SC", "South Carolina")); 
    arrList.Add(new KeyValuePair<string, string>("SD", "South Dakota")); 
    arrList.Add(new KeyValuePair<string, string>("TN", "Tennessee")); 
    arrList.Add(new KeyValuePair<string, string>("TX", "Texas")); 
    arrList.Add(new KeyValuePair<string, string>("UT", "Utah")); 
    arrList.Add(new KeyValuePair<string, string>("VT", "Vermont")); 
    arrList.Add(new KeyValuePair<string, string>("VA", "Virginia")); 
    arrList.Add(new KeyValuePair<string, string>("WA", "Washington")); 
    arrList.Add(new KeyValuePair<string, string>("WV", "West Virginia")); 
    arrList.Add(new KeyValuePair<string, string>("WI", "Wisconsin")); 
    arrList.Add(new KeyValuePair<string, string>("WY", "Wyoming")); 
    return arrList; 
} 
+0

+1 gusta mucho la idea de crear extensiones personalizadas para resolver cualquier cuestión así ... realmente – Fabian

2

Usé una clase de ayuda para eso. es bastante simple en realidad. Con la clase de ayuda, puede usar una lista de selección y ponerla en el asistente, como lo haría con un menú desplegable.

en los "ayudantes" de carpetas que tengo Checkboxlist.cs

using System; 
    using System.Web.Mvc; 
    using System.Collections.Generic; 
    using System.Text; 
    using System.Linq; 

    namespace MVC2_NASTEST.Helpers { 
     public static class CheckBoxListHelper { 

      public static string CheckBoxList(this HtmlHelper helper, string name, IDictionary<string, string> items) { 
       return CheckBoxList(helper, name, items, null, null); 
      } 

      public static string CheckBoxList(this HtmlHelper helper, string name, IDictionary<string, string> items, IDictionary<string, object> checkboxHtmlAttributes) { 
       return CheckBoxList(helper, name, items, null, checkboxHtmlAttributes); 
      } 

      public static string CheckBoxList(this HtmlHelper helper, string name, IDictionary<string, string> items, IEnumerable<string> selectedValues) { 
       return CheckBoxList(helper, name, items, selectedValues, null); 
      } 

      public static string CheckBoxList(this HtmlHelper helper, string name, IDictionary<string, string> items, IEnumerable<string> selectedValues, IDictionary<string, object> checkboxHtmlAttributes) { 

       var selectListItems = from i in items 
             select new SelectListItem { 
              Text = i.Key, 
              Value = i.Value, 
              Selected = (selectedValues != null && selectedValues.Contains(i.Value)) 
             }; 

       return CheckBoxList(helper, name, selectListItems, checkboxHtmlAttributes); 
      } 

      public static string CheckBoxList(this HtmlHelper helper, string name, IEnumerable<SelectListItem> items) { 
       return CheckBoxList(helper, name, items, null); 
      } 

      public static string CheckBoxList(this HtmlHelper helper, string name, IEnumerable<SelectListItem> items, IDictionary<string, object> checkboxHtmlAttributes) { 
       var output = new StringBuilder(); 

       foreach (var item in items) { 
        output.Append("<div class=\"fields\"><label>"); 
        var checkboxList = new TagBuilder("input"); 
        checkboxList.MergeAttribute("type", "checkbox"); 
        checkboxList.MergeAttribute("name", name); 
        checkboxList.MergeAttribute("value", item.Value); 

        // Check to see if it's checked 
        if (item.Selected) 
         checkboxList.MergeAttribute("checked", "checked"); 

        // Add any attributes 
        if (checkboxHtmlAttributes != null) 
         checkboxList.MergeAttributes(checkboxHtmlAttributes); 

        checkboxList.SetInnerText(item.Text); 
        output.Append(checkboxList.ToString(TagRenderMode.SelfClosing)); 
        output.Append("&nbsp; " + item.Text + "</label></div>"); 
       } 

       return output.ToString(); 
      } 
     } 
    } 

el código en mi controlador:

public static List<SelectListItem> lesgeverList() { 
     return lesgeverList(-1); 
    } 

    public static List<SelectListItem> lesgeverList(int selectedID) { 
     return lesgeverList(new int[] { selectedID }); 
    } 

    public static List<SelectListItem> lesgeverList(int[] lg) { 
     NASDataContext _db = new NASDataContext(); 
     var lesg = (from l in _db.Lesgevers 
        where l.LG_Naam != "leeg" 
        orderby l.LG_Naam, l.LG_Vnaam 
        select l).ToSelectList(m => m.LG_Naam + " " + m.LG_Vnaam, m => m.LG_ID.ToString(), m => lg.Contains(m.LG_ID)); 
     return lesg.ToList(); 
    } 

    // 
    // GET: /Projectleiders/Create 

    public ActionResult Create(int projID) { 
     ViewData["projNaam"] = getProject(projID).Proj_Kortenaam; 
     int[] keys = (from p in _db.ProjectleiderProjectens 
         where p.Proj_ID == projID 
         from l in _db.Lesgevers 
         where p.LG_ID == l.LG_ID 
         select l.LG_ID).ToArray(); 

     ViewData["projleiders"] = MvcApplication.lesgeverList(keys); 

     return toegankelijk(projID, null); 
    } 

    // 
    // POST: /Projectleiders/Create 

    [HttpPost] 
    public ActionResult Create(FormCollection collection, int projID) { 

     if (collection["lesgeverlist"] != null) { 
      string[] lgevers = collection["lesgeverlist"].Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); 
      List<ProjectleiderProjecten> lst = new List<ProjectleiderProjecten>(); 
      foreach (string s in lgevers) { 
       ProjectleiderProjecten prl = new ProjectleiderProjecten(); 
       prl.LG_ID = int.Parse(s); 
       prl.Proj_ID = projID; 

       int count = (from m in _db.ProjectleiderProjectens 
          where m.LG_ID == prl.LG_ID && m.Proj_ID == prl.Proj_ID 
          select m).Count(); 

       if (count <= 0) { 
        //deze bestaat nog niet 
        lst.Add(prl); 
       } 
      } 
      //var test = _db.ProjectleiderProjectens.Where(p => p.Proj_ID == projID && !lgevers.Contains(p.LG_ID.ToString())).ToList(); 

      _db.ProjectleiderProjectens.DeleteAllOnSubmit(_db.ProjectleiderProjectens.Where(p => p.Proj_ID == projID && !lgevers.Contains(p.LG_ID.ToString()))); 

      _db.ProjectleiderProjectens.InsertAllOnSubmit(lst); 
      _db.SubmitChanges(); 

      return RedirectToAction("Index"); 
     } else { 

      ModelState.AddModelError("lesgeverlist", "Je hebt geen lesgevers geselecteerd"); 

      ViewData["projleiders"] = MvcApplication.lesgeverList(); 
      ViewData["projNaam"] = getProject(projID).Proj_Kortenaam; 
      return View(); 
     } 
    } 

que utilizan la extensión ToSelectList que es algo que todos deberían tener.

public static class VSKOExtensions { 
    public static IList<SelectListItem> ToSelectList<T>(this IEnumerable<T> itemsToMap, Func<T, string> textProperty, Func<T, string> valueProperty, Predicate<T> isSelected) { 
     var result = new List<SelectListItem>(); 

     foreach (var item in itemsToMap) { 
      result.Add(new SelectListItem { 
       Value = valueProperty(item), 
       Text = textProperty(item), 
       Selected = isSelected(item) 
      }); 
     } 
     return result; 
    } 
} 

el código en mi crear vistas (que también es una vista de edición en el mismo tiempo) es muy simple

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MVC2_NASTEST.Models.ProjectleiderProjecten>" %> 
    <%@ Import Namespace="MVC2_NASTEST.Helpers" %> 

    <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> 
     Create 
    </asp:Content> 

    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 

     <h2>Koppel projectleider voor 
      <%= ViewData["projNaam"].ToString() %></h2> 

     <% using (Html.BeginForm()) {%> 
      <%= Html.ValidationSummary(true) %> 

      <fieldset> 
       <legend>Fields</legend> 

       <div class="editor-label"> 
        <%= Html.Label("Lesgevers")%> 
       </div> 
       <div class="editor-field"> 
        <%= Html.CheckBoxList("Lesgeverlist", ViewData["projleiders"] as List<SelectListItem>)%> 
        <%= Html.ValidationMessage("Lesgeverlist")%> 
       </div> 

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

     <% } %> 

     <div> 
      <%= Html.ActionLink("Back to List", "Index") %> 
     </div> 

    </asp:Content> 

como funciona:

i obtener los valores de la BD de los usuarios ya seleccionados, obtenga sus id y déselos al método MvcApplication.lesgeverList (claves);

luego recupero la lista de selección, la pongo en los datos de vista, y las personas seleccionadas se seleccionan en mi vista cuando lo abro. luego, cuando cambio algunos cuadros y los guardo, compruebo si la colección no es nula (para que algo esté seleccionado) y luego divido las variables que obtengo, que son los "valores que das en la Lista de selección". Los busco, los analizo a los enteros, obtengo los usuarios del DB con sus identificaciones analizadas. Con el conteo veo si existen o no en la tabla 'vinculada' que se llama _db.ProjectleiderProjectens

cuando todo se añaden, i eliminar todos los no seleccionados '' en 1 hora con la declaración de LINQ

_db.ProjectleiderProjectens.DeleteAllOnSubmit(_db.ProjectleiderProjectens.Where(p => p.Proj_ID == projID && !lgevers.Contains(p.LG_ID.ToString()))); 

que creo que es bastante fácil de leer. eliminar todos los objetos, obtener todos los objetos de su ID y comprobar cuáles no están en la cadena [] de ID

funciona bastante bien, debo decir. si tiene más preguntas solo pregunte.

+0

+1 uso increíble de extensiones con .CheckBoxList() .ToSelectList () ... psst ViewData -> ¡malo! : D – Fabian

+0

Entonces, ¿qué usas en lugar de ViewData para este tipo de cosas? :) No soy un gran admirador, pero no conozco una mejor solución. – Stefanvds

+0

Pasaría esa información a través del modelo de vista – Fabian

0

Simplemente use jQuery validate en el lado del cliente y luego doble verificación en el lado del servidor solo asegúrese de que la colección de formularios tenga un valor poblado.

No hay nada de malo con su bucle for.

+0

No tengo acceso al único objeto del cliente (del ciclo) en la expresión labmda – Fabian

+0

No sé la respuesta, pero podría hacer e inserte lo que quiera. –

3

Html.CheckBoxFor() método de extensión está diseñado para editar propiedad del modelo de tipo booleano. Desea usarlo para seleccionar algunos objetos de la colección IEnumerable. Está incorrecto.

manera correcta:

en vista

<form action="/Customer/Process"> 
<% foreach (var customer in Model.Request.Customers) 
    { %> 
     <input type="checkbox" name="selectedId" value="<%= customer.id %>" /> 
     <%= customer.name %> 
     <br/> 
<% } %> 
     <input type="submit"/> 
</form> 

en el controlador

public string Process(IEnumerable<Guid> selectedId) 
{ 
    if (selectedId == null) 
    { 
     ModelState.AddModelError("selectedId", "Have to select at least one customer!"); 

     return View(); 
    } 

    // do something with customers' ids 
} 
+0

Como la simplicidad de este método. :) –

+0

Simple y funciona. –

Cuestiones relacionadas