Hoe om te gaan met selectievakjes in ASP.NET MVC-formulieren?

U kunt het beste naar nieuwere vragen zoeken, of de onderstaande antwoorden zoeken op zoek naar uw specifieke versie van MVC, aangezien veel antwoorden hier nu achterhaald zijn.

Als u een antwoord vindt dat werkt voor uw versie, zorg er dan voor dat het antwoord de versie van MVC bevat die u gebruikt.
(De oorspronkelijke vraag begint hieronder)


Dit lijkt me een beetje bizar, maar voor zover ik weet, is dit hoe je het doet.

Ik heb een verzameling objecten en ik wil dat gebruikers er een of meer van selecteren. Dit zegt tegen mij “formulier met selectievakjes”. Mijn objecten hebben geen concept van “geselecteerd” (het zijn rudimentaire POCO’s gevormd door het deserialiseren van een wcf-oproep). Dus doe ik het volgende:

public class SampleObject{
  public Guid Id {get;set;}
  public string Name {get;set;}
}

In de weergave:

<%
    using (Html.BeginForm())
    {
%>
  <%foreach (var o in ViewData.Model) {%>
    <%=Html.CheckBox(o.Id)%>&nbsp;<%= o.Name %>
  <%}%>
  <input type="submit" value="Submit" />
<%}%>

En in de controller is dit de enige manier waarop ik kan zien welke objecten de gebruiker heeft gecontroleerd:

public ActionResult ThisLooksWeird(FormCollection result)
{
  var winnars = from x in result.AllKeys
          where result[x] != "false"
          select x;
  // yadda
}

Het is in de eerste plaats freaky, en ten tweede, voor die items die de gebruiker heeft gecontroleerd, vermeldt de FormCollection de waarde als “true false” in plaats van alleen waar.

Natuurlijk mis ik iets. Ik denk dat dit is gebouwd met het idee in het achterhoofd dat de objecten in de collectie waarop in het html-formulier wordt gereageerd, worden bijgewerkt met behulp van UpdateModel()of via een ModelBinder.

Maar mijn objecten zijn hier niet op ingesteld; betekent dat dat dit de enige manier is? Is er een andere manier om het te doen?


Antwoord 1, autoriteit 100%

Html.CheckBox doet iets raars – als je de bron bekijkt op de resulterende pagina, zul je zien dat er een <input type="hidden" />wordt gegenereerd naast elk selectievakje, wat de “true false”-waarden verklaart die u voor elk formulierelement ziet.

Probeer dit, wat zeker werkt op ASP.NET MVC Beta, want ik heb het net geprobeerd.

Zet dit in de weergave in plaats van Html.CheckBox():

<% using (Html.BeginForm("ShowData", "Home")) {  %>
  <% foreach (var o in ViewData.Model) { %>
    <input type="checkbox" name="selectedObjects" value="<%=o.Id%>">
    <%= o.Name %>
  <%}%>
  <input type="submit" value="Submit" />
<%}%>

Uw selectievakjes heten allemaal selectedObjectsen de valuevan elk selectievakje is de GUID van het bijbehorende object.

Plaats vervolgens naar de volgende controlleractie (of iets dergelijks dat iets nuttigs doet in plaats van Response.Write())

public ActionResult ShowData(Guid[] selectedObjects) {
    foreach (Guid guid in selectedObjects) {
        Response.Write(guid.ToString());
    }
    Response.End();
    return (new EmptyResult());
}

Dit voorbeeld schrijft alleen de GUID’s van de vakjes die je hebt aangevinkt; ASP.NET MVC wijst de GUID-waarden van de geselecteerde selectievakjes toe aan de parameter Guid[] selectedObjectsvoor u, en parseert zelfs de tekenreeksen van de Request.Form-verzameling naar de GUID-objecten van de autoriteiten, wat volgens mij nogal leuk.


Antwoord 2, autoriteit 36%

HtmlHelper voegt een verborgen invoer toe om de controller op de hoogte te stellen van de status Niet-aangevinkt.
Dus om de juiste gecontroleerde status te hebben:

bool bChecked = form[key].Contains("true");

Antwoord 3, autoriteit 21%

In het geval je je afvraagt ​​WAAROM ze een verborgen veld hebben geplaatst met dezelfde naam als het selectievakje, de reden is als volgt:

Commentaar van de broncode MVCBetaSource\MVC\src\MvcFutures\Mvc\ButtonsAndLinkExtensions.cs

Geef een extra <input
type="hidden".../>
voor selectievakjes.
Dit behandelt scenario’s waarin:
niet aangevinkte selectievakjes worden niet ingestuurd
de aanvraag. Een verborgen invoer verzenden
maakt het mogelijk om te weten dat de
checkbox was aanwezig op de pagina toen
het verzoek is ingediend.

Ik denk dat ze dit achter de schermen moeten weten om te kunnen binden aan parameters op de actiemethoden van de controller. Je zou dan een tri-state boolean kunnen hebben, denk ik (gebonden aan een nullable bool-parameter). Ik heb het niet geprobeerd, maar ik hoop dat ze dat hebben gedaan.


Antwoord 4, autoriteit 19%

U moet ook <label for="checkbox1">Checkbox 1</label>gebruiken omdat mensen dan zowel op de labeltekst als op het selectievakje zelf kunnen klikken. Het is ook gemakkelijker te stylen en in IE wordt het in ieder geval gemarkeerd als je door de bedieningselementen van de pagina bladert.

<%= Html.CheckBox("cbNewColors", true) %><label for="cbNewColors">New colors</label>

Dit is niet zomaar een ‘oh ik zou het kunnen’-ding. Het is een aanzienlijke verbetering van de gebruikerservaring. Zelfs als niet alle gebruikers weten dat ze op het label kunnen klikken, zullen velen dat wel doen.


Antwoord 5, autoriteit 10%

Het verbaast me dat geen van deze antwoorden de ingebouwde MVC-functies hiervoor heeft gebruikt.

Ik heb een blogpost geschreven over deze hier, die zelfs de labels daadwerkelijk aan het selectievakje koppelt. Ik heb de map EditorTemplategebruikt om dit op een overzichtelijke en modulaire manier te doen.

Je krijgt gewoon een nieuw bestand in de EditorTemplate-map dat er als volgt uitziet:

@model SampleObject
@Html.CheckBoxFor(m => m.IsChecked)
@Html.HiddenFor(m => m.Id)
@Html.LabelFor(m => m.IsChecked, Model.Id)

in uw werkelijke weergave is het niet nodig om dit te herhalen, slechts 1 regel code:

@Html.EditorFor(x => ViewData.Model)

Bezoek mijn blogberichtvoor meer details.


Antwoord 6, autoriteit 10%

Dit is wat ik heb gedaan.

Bekijken:


<input type="checkbox" name="applyChanges" />

Controller:


var checkBox = Request.Form["applyChanges"];
if (checkBox == "on")
{
...
}

Ik vond de Html.*-helpermethoden in sommige gevallen niet zo handig, en dat ik het beter in gewone, oude HTML kon doen. Dit is er een van, de andere die in je opkomt zijn keuzerondjes.

Bewerken: dit is in Preview 5, uiteraard YMMV tussen versies.


Antwoord 7, autoriteit 4%

Het lijkt erop dat ze ervoor kiezen om alleen de eerste waarde te lezen, dus dit is “true” wanneer het selectievakje is aangevinkt en “false” wanneer alleen de verborgen waarde is opgenomen. Dit is gemakkelijk op te halen met de volgende code:

model.Property = collection["ElementId"].ToLower().StartsWith("true");

8, Autoriteit 2%

Dit probleem gebeurt ook in de release 1.0. HTML.CheckBox () zorgt ervoor dat een ander verborgen veld met dezelfde naam / ID als van uw originele selectievakje wordt toegevoegd. En terwijl ik probeerde een checkbox-array op te laden met behulp van Document.getelemTentsByName (), kun je raden hoe de dingen verknoeien. Het is een bizar.


Antwoord 9, autoriteit 2%

Ik weet dat deze vraag is geschreven toen MVC3 nog niet uit was, maar voor iedereen die op deze vraag komt en MVC3 gebruikt, wil je misschien de “juiste” manier om dit te doen.

Terwijl ik denk dat het hele doen

Contains("true");

ding is geweldig en schoon, en werkt op alle MVC-versies, het probleem is dat het geen rekening houdt met cultuur (alsof het er echt toe doet in het geval van een bool).

De “juiste” manier om de waarde van een bool te achterhalen, in ieder geval in MVC3, is door de ValueProvider te gebruiken.

var value = (bool)ValueProvider.GetValue("key").ConvertTo(typeof(bool));

Ik doe dit op een van de sites van mijn klant wanneer ik machtigingen bewerk:

var allPermissionsBase = Request.Params.AllKeys.Where(x => x.Contains("permission_")).ToList();
var allPermissions = new List<KeyValuePair<int, bool>>();
foreach (var key in allPermissionsBase)
{
     // Try to parse the key as int
     int keyAsInt;
     int.TryParse(key.Replace("permission_", ""), out keyAsInt);
     // Try to get the value as bool
     var value = (bool)ValueProvider.GetValue(key).ConvertTo(typeof(bool));
}

Het mooie hiervan is dat je dit met zowat elk eenvoudig type kunt gebruiken, en het zal zelfs correct zijn op basis van de cultuur (denk aan geld, decimalen, enz.).

De ValueProvider is wat wordt gebruikt wanneer u uw acties als volgt vormgeeft:

public ActionResult UpdatePermissions(bool permission_1, bool permission_2)

maar wanneer u deze lijsten dynamisch probeert op te bouwen en de waarden te controleren, zult u de id tijdens het compileren nooit weten, dus u moet ze meteen verwerken.


Antwoord 10

De gemakkelijkste manier om dit te doen is zo…

U stelt de naam en waarde in.

<input type="checkbox" name="selectedProducts" value="@item.ProductId" />@item.Name

Bij het indienen pak je de waarden van de selectievakjes en sla je ze op in een int-array.
vervolgens de juiste LinQ-functie. Dat is het..

[HttpPost]
        public ActionResult Checkbox(int[] selectedObjects)
        {
            var selected = from x in selectedObjects
                           from y in db
                           where y.ObjectId == x
                           select y;                   
            return View(selected);
        }

Antwoord 11

Hetzelfde als het antwoord van nautic20, gebruik gewoon de MVC-lijst met standaardmodelbinding-selectievakjes met dezelfde naam als een verzamelingseigenschap van string/int/enum in ViewModel. Dat is het.

Maar er moet op één probleem worden gewezen. In elke component met selectievakjes moet u geen “Id” erin zetten, wat de MVC-modelbinding beïnvloedt.

De volgende code werkt voor modelbinding:

<% foreach (var item in Model.SampleObjectList)
       { %>
        <tr>
            <td><input type="checkbox" name="SelectedObjectIds" value="<%= item.Id%>" /></td>
            <td><%= Html.Encode(item.Name)%></td>
        </tr>
 <% } %>

De volgende codes zijn niet bindend voor het model (het verschil is dat er voor elk selectievakje een id wordt toegewezen)

<% foreach (var item in Model.SampleObjectList)
       { %>
        <tr>
            <td><input type="checkbox" name="SelectedObjectIds" id="[some unique key]" value="<%= item.Id%>" /></td>
            <td><%= Html.Encode(item.Name)%></td>
        </tr>
<% } %>

Antwoord 12

dit is wat ik deed om de dubbele waarden te verliezen bij het gebruik van de Html.CheckBox(…

Replace("true,false","true").Split(',')

met 4 vakjes aangevinkt, niet aangevinkt, uitgevinkt, aangevinkt draait het om
waar, onwaar, onwaar, onwaar, waar, onwaar
naar binnen
waar, onwaar, onwaar, waar.
precies wat ik nodig had


Antwoord 13

Wat dacht je van zoiets?

bool isChecked = false;
if (Boolean.TryParse(Request.Form.GetValues(”chkHuman”)[0], out isChecked) == false)
    ModelState.AddModelError(”chkHuman”, “Nice try.”);

Antwoord 14

Als ik het selectievakje HtmlHelper gebruik, werk ik veel liever met de geposte formuliergegevens van het selectievakje als een array. Ik weet niet echt waarom, ik weet dat de andere methoden werken, maar ik denk dat ik gewoon de voorkeur geef om door komma’s gescheiden strings zo veel mogelijk als een array te behandelen.

Dus het doen van een ‘checked’ of true test zou zijn:

//looking for [true],[false]
bool isChecked = form.GetValues(key).Contains("true"); 

Een valse controle doen zou zijn:

//looking for [false],[false] or [false]
bool isNotChecked = !form.GetValues(key).Contains("true"); 

Het belangrijkste verschil is om GetValueste gebruiken omdat dit als een array terugkeert.


Antwoord 15

Doe dit gewoon op $(document).ready:

$('input:hidden').each(function(el) {
    var that = $(this)[0];
    if(that.id.length < 1 ) {
        console.log(that.id);
        that.parentElement.removeChild(that);
    }
});

Antwoord 16

Mijn oplossing is:

<input type="checkbox"  id="IsNew-checkbox"  checked="checked" />     
<input type="hidden"  id="IsNew" name="IsNew" value="true"  />      
<script language="javascript" type="text/javascript" >     
  $('#IsNew-checkbox').click(function () {    
      if ($('#IsNew-checkbox').is(':checked')) {    
          $('#IsNew').val('true');    
      } else {    
          $('#IsNew').val('false');    
       }    
  });   
</script>  

Meer vind je hier:
http://www.blog.mieten.pl/2010/12/asp-net-mvc-custom-checkbox-as-solution-of-string-was-not-recognized- as-a-valid-boolean/


Antwoord 17

Ik had bijna hetzelfde probleem, maar de retourwaarde van mijn controller werd geblokkeerd met andere waarden.

Een eenvoudige oplossing gevonden, maar het lijkt een beetje ruw.

Probeer Viewbag.in je Controller te typen en nu geef je het een naam als Viewbag.Checkbool

Schakel nu over naar de View en probeer deze @Viewbag.Checkboolhiermee haal je de waarde uit de Controller.

Mijn controllerparameters zien er als volgt uit:

public ActionResult Anzeigen(int productid = 90, bool islive = true)

en mijn selectievakje wordt als volgt bijgewerkt:

<input id="isLive" type="checkbox" checked="@ViewBag.Value" ONCLICK="window.location.href = '/MixCategory/Anzeigen?isLive=' + isLive.checked.toString()" />

Antwoord 18

Met @mmacaaulay bedacht ik dit voor bool:

// MVC Work around for checkboxes.
bool active = (Request.Form["active"] == "on");

Indien aangevinkt
actief = waar

Indien niet aangevinkt
actief = onwaar

Other episodes