2010-08-12 9 views
6

Ich arbeite auf einer Seite, wo der Benutzer einige Informationen ausfüllen und schließlich eine Auswahl von 1 oder mehr Kunden mit Kontrollkästchen auswählen muss.Wie verwende ich Html.CheckBox (Liste) mit IEnumerable <T> mit Validierung

Die Liste der Kunden ist eine IEnumerable<Customer>, die ich in mein Modell übertrage. Wie würde ich die Liste der Kontrollkästchen mit .CheckBoxFor() erstellen?

Und schließlich möchte ich validieren können, wenn mindestens 1 Check-Box ausgewählt wurde.

Anforderung ist das Objekt, das die vom Benutzer eingegebenen Informationen enthält.

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

Kann mir jemand in die richtige Richtung zeigen? Oder mache ich das alles falsch?

Antwort

3

Sie könnten eine benutzerdefinierte HTML-Erweiterung Klasse erstellen und die CheckBoxFor-Methode wie unten überladen. Die Methode wertet das metadata.Model auf den übergebenen Wert aus (wie US-State). Sie können das Kontrollkästchen Wert/s aus der Formcollection im ControllerAction erhalten:

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

    // perform validation 
    .... 
} 

Beispiel nimmt eine KeyValuePair generische Liste

<% 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)); 
     } 
    } 

Während ich bin bei es, hier ist meine Liste der Vereinigten Staaten, um den Code zu vervollständigen:

/// <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 wirklich wie die Idee, individuelle Erweiterungen schaffen zu lösen ... und jede Ausgabe wirklich – Fabian

2

Ich habe dafür eine Helferklasse benutzt. es ist wirklich ziemlich einfach. Mit der Helper-Klasse können Sie eine SelectList verwenden und sie in den Helper einfügen, wie Sie es für ein DropDown tun würden.

in den Ordner "Helpers" Ich habe 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(); 
      } 
     } 
    } 

den Code in meinem Controller:

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(); 
     } 
    } 

ich die ToSelectList Erweiterung verwenden, die haben sollte für jeden etwas dabei ist.

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; 
    } 
} 

der Code in meinem erstellen Ansicht (die auch eine Bearbeitungsansicht in der gleichen Zeit ist)

<%@ 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> 

sehr einfach ist, wie es funktioniert:

i die Werte aus der DB erhalten der bereits ausgewählten Benutzer erhalten ihre IDs und geben sie an die Methode MvcApplication.lesgeverList (keys);

dann bekomme ich die selectlist zurück, lege sie in die viewdata, und die ausgewählten personen werden in meiner sicht ausgewählt, wenn ich sie öffne. dann, wenn ich einige Kästchen ändere und es speichere, überprüfe ich, ob die Sammlung nicht null ist (also etwas ausgewählt ist), dann teile ich die Variablen, die ich zurückbekomme, welche die Werte sind, die du in der Auswahlliste gibst. Ich foreach durch sie, parse sie zu Ints, holen Sie die Benutzer von der DB mit ihren analysierten IDs. Mit der Zählung schaue ich, ob sie in der verknüpften Tabelle existieren oder nicht, die _db heißt.ProjectleiderProjectens

wenn alle hinzugefügt werden, löschen i alle ‚nicht ausgewählten‘ Einsen in 1mal die Linq-Anweisung

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

, die ich denke, ziemlich lesbar ist. lösche alle Objekte von, lies alle Objekte ihre ID und überprüfe, welche nicht in der Zeichenkette [] von IDs sind

es funktioniert ziemlich gut ich muss sagen. Wenn Sie noch Fragen haben, fragen Sie einfach.

+0

+1 tolle Verwendung von Erweiterungen mit .CheckBoxList() .ToSelectList () ... psst ViewData -> schlecht! : D – Fabian

+0

Was verwenden Sie anstelle von ViewData für diese Art von Dingen? :) kein großer Fan davon, aber kenne keine bessere Lösung. – Stefanvds

+0

Ich würde diese Informationen durch die Ansicht übergeben Modell – Fabian

0

Verwenden Sie einfach jQuery validate auf der Clientseite und dann überprüfen Sie sich selbst auf der Serverseite nur sicherstellen, dass die Formularsammlung einen Wert ausgefüllt hat.

Es ist nichts falsch mit Ihrer for-Schleife.

+0

Ich habe keinen Zugriff auf die einzelnen Kundenobjekt (aus der Schleife) in der Labmda-Ausdruck – Fabian

+0

Ich weiß nicht die Antwort, aber Sie könnten einfach tun und fügen Sie ein, was Sie wollen. –

3

Html.CheckBoxFor() Erweiterung Methode wurde entwickelt, um bearbeiten Modell Eigenschaft des Typs Boolean. Sie möchten damit Objekte aus der IEnumerable-Sammlung auswählen. Es ist falsch.

Richtiger Weg:

im Blick

<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> 

in Controller

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

Wie die Einfachheit dieser Methode. :) –

+0

Einfach und es funktioniert. –

Verwandte Themen