Jak obchodzić się z checkboxami w ASP.NET formularze MVC?

Uwaga: to pytanie ma ponad dziewięć lat!

Najlepszą opcją jest wyszukiwanie nowszych pytań lub wyszukiwanie poniższych odpowiedzi w poszukiwaniu konkretnej wersji MVC, ponieważ wiele odpowiedzi tutaj jest już przestarzałych.

Jeśli znajdziesz odpowiedź, która działa dla twojej wersji, upewnij się, że odpowiedź zawiera wersję MVC, której używasz.
(oryginalne pytanie zaczyna się poniżej)


Wydaje mi się to trochę dziwne, ale jeśli chodzi o Widzę, że tak to się robi.

Mam kolekcję obiektów i chcę, aby użytkownicy wybierali jeden lub więcej z nich. Tu jest napisane " formularz z checkboxami."Moje obiekty nie mają pojęcia "wybrane" (są to podstawowe POCO ' s utworzone przez deserializację wywołania wcf). Więc robię co następuje:

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

W widoku:

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

I, w kontrolerze, jest to jedyny sposób, aby dowiedzieć się, jakie obiekty użytkownik sprawdzał:

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

Jego dziwaczne w pierwszym miejsce, a po drugie, dla tych elementów, które użytkownik sprawdzał, FormCollection wyświetla swoją wartość jako "true false", a nie tylko true.

Najwyraźniej coś mi umyka. Myślę, że jest to zbudowane z myślą o tym, że obiekty w kolekcji, które działają w formularzu html, są aktualizowane za pomocą UpdateModel() lub za pomocą Modelbindera.

Ale moje obiekty nie są ustawione do tego; czy to znaczy, że to jedyny sposób? Jest na to inny sposób?

Author: Uwe Keim, 2008-10-21

22 answers

Html.Pole wyboru robi coś dziwnego - jeśli wyświetlisz źródło na stronie wynikowej, zobaczysz, że obok każdego pola jest generowana <input type="hidden" />, co wyjaśnia wartości "true false", które widzisz dla każdego elementu formularza.

Spróbuj tego, co zdecydowanie działa na ASP.NET MVC Beta bo właśnie próbowałem.

Umieść to w widoku zamiast używać 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" />
<%}%>

Wszystkie twoje pola są nazywane selectedObjects, a value każdego pola jest identyfikatorem GUID odpowiedni obiekt.

Następnie wyślij post do następującej akcji kontrolera (lub czegoś podobnego, co robi coś użytecznego zamiast odpowiedzi.Write ())

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

Ten przykład po prostu zapisze GUID zaznaczonych pól; ASP.NET MVC mapuje wartości GUID zaznaczonych pól wyboru do parametru Guid[] selectedObjects, a nawet przetwarza Ciągi z żądania.Form collection into instanted GUID objects, co moim zdaniem jest dość miłe.

 262
Author: Dylan Beattie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-20 21:49:11

HtmlHelper dodaje ukryte wejście, aby powiadomić kontroler o Niezaznaczonym statusie. Więc aby mieć poprawny sprawdzony status:

bool bChecked = form[key].Contains("true");
 95
Author: Andrea Balducci,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-12 15:55:40

Jeśli zastanawiasz się, dlaczego umieścili ukryte pole o tej samej nazwie, co pole wyboru, powód jest następujący:

Komentarz z kodu źródłowego MVCBetaSource \ MVC \ src \ MvcFutures \ Mvc\ ButtonsAndLinkExtensions.cs

Renderuje dodatkowe <input type="hidden".../> dla pól wyboru. Dotyczy to scenariuszy, w których niezaznaczone pola wyboru nie są wysyłane Prośba. Wysyłanie ukrytego wejścia umożliwia poznanie, że checkbox był obecny na stronie, gdy na wniosek został złożony.

Myślę, że za kulisami muszą to wiedzieć, aby powiązać parametry z metodami akcji kontrolera. Można wtedy mieć Tri-state boolean przypuszczam (związany z nullable bool parametr). Nie próbowałem, ale mam nadzieję, że tak zrobili.

 54
Author: Simon_Weaver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-30 00:05:49

Powinieneś również użyć <label for="checkbox1">Checkbox 1</label>, ponieważ wtedy ludzie mogą kliknąć na etykiecie, a także na samym polu wyboru. Jego również łatwiejsze do stylu i przynajmniej w IE będzie podświetlony, gdy zakładka za pomocą kontrolek strony.

<%= Html.CheckBox("cbNewColors", true) %><label for="cbNewColors">New colors</label>
To nie jest tylko "Oh I could do it". Jego znaczące zwiększenie doświadczenia użytkownika. Nawet jeśli nie wszyscy użytkownicy wiedzą, że mogą kliknąć Etykietę, wielu będzie.
 49
Author: Simon_Weaver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-27 21:14:51

Jestem zaskoczony, że żadna z tych odpowiedzi nie użyła do tego wbudowanych funkcji MVC.

Napisałem post na blogu o tym tutaj , który nawet faktycznie łączy etykiety z checkboxem. Użyłem folderu EditorTemplate , aby osiągnąć to w sposób przejrzysty i modułowy.

Po prostu skończysz z nowym plikiem w folderze EditorTemplate, który wygląda tak:

@model SampleObject

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

W Twoim rzeczywistym widoku, nie będzie potrzeby pętli tego, po prostu 1 linia kod:

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

Odwiedź mój blog post Po Więcej Szczegółów.

 27
Author: Shawn Mclean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-05 20:42:47

Oto, co robiłem.

Widok:


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

Kontroler:


var checkBox = Request.Form["applyChanges"];

if (checkBox == "on")
{
...
}

Znalazłem Html.* metody pomocnicze nie są tak przydatne w niektórych przypadkach, i że lepiej było robić to w zwykłym starym HTML. Ten jest jednym z nich, drugi, który przychodzi na myśl, to przyciski radiowe.

Edit: to jest na podglądzie 5, oczywiście YMMV między wersjami.

 25
Author: mmacaulay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-20 21:59:51

Wydają się decydować o odczycie tylko pierwszej wartości, więc jest to "prawda", gdy pole wyboru jest zaznaczone, i "fałsz", gdy zawiera tylko ukrytą wartość. Można to łatwo pobrać za pomocą takiego kodu:

model.Property = collection["ElementId"].ToLower().StartsWith("true");
 10
Author: Fluffy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-20 20:36:06

@ Dylan Beattie Great Find!!! Bardzo dziękuję. Aby jeszcze bardziej rozszerzyć tę technikę, doskonale sprawdza się również w podejściu do modelu widoku. MVC jest tak fajny, że jest wystarczająco inteligentny, aby powiązać tablicę GUID z właściwością o tej samej nazwie obiektu modelu powiązanego z widokiem. Przykład:

ViewModel:

public class SampleViewModel
{
    public IList<SampleObject> SampleObjectList { get; set; }
    public Guid[] SelectedObjectIds { get; set; }

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

Widok:

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Sample View</h2>
<table>
    <thead> 
        <tr>
            <th>Checked</th>
            <th>Object Name</th>
        </tr>
    </thead> 
<% using (Html.BeginForm()) %>
<%{%>                    
    <tbody>
        <% foreach (var item in Model.SampleObjectList)
           { %>
            <tr>
                <td><input type="checkbox" name="SelectedObjectIds" value="<%= item.Id%>" /></td>
                <td><%= Html.Encode(item.Name)%></td>
            </tr>
        <% } %>
    </tbody>
</table>
<input type="submit" value="Submit" />
<%}%>                    

Kontroler:

    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult SampleView(Guid id)
    {
        //Object to pass any input objects to the View Model Builder 
        BuilderIO viewModelBuilderInput = new BuilderIO();

        //The View Model Builder is a conglomerate of repositories and methods used to Construct a View Model out of Business Objects
        SampleViewModel viewModel = sampleViewModelBuilder.Build(viewModelBuilderInput);

        return View("SampleView", viewModel);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult SampleView(SampleViewModel viewModel)
    {
        // The array of Guids successfully bound to the SelectedObjectIds property of the View Model!
        return View();
    }

Każdy, kto zna filozofię modelu widzenia, będzie zadowolony, to działa jak mistrz!

 8
Author: nautic20,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-04 15:24:48

Chciałbym również zwrócić uwagę, że każde pole wyboru można nazwać inną nazwą i mieć tę nazwę jako część parametrów actionresults.

Przykład,

Widok:

 <%= Html.CheckBox("Rs232CheckBox", false, new { @id = "rs232" })%>RS-232

 <%= Html.CheckBox("Rs422CheckBox", false, new { @id = "rs422" })%>RS-422

Kontroler:

public ActionResults MyAction(bool Rs232CheckBox, bool Rs422CheckBox) {
    ...
}

Wartości z widoku są przekazywane do akcji, ponieważ nazwy są takie same.

Wiem, że to rozwiązanie nie jest idealne dla Twojego projektu, ale pomyślałem, że wyrzucę ten pomysł.
 6
Author: Darcy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-22 14:48:25
<input type = "checkbox" name = "checkbox1" /> <label> Check to say hi.</label>

Od kontrolera:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Index(FormCollection fc)
    {

         var s = fc["checkbox1"];

         if (s == "on")
         {
             string x = "Hi";
         }
    }
 5
Author: bluwater2001,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-21 19:41:28

Ten problem występuje również w wersji 1.0. Html.Checkbox () powoduje dodanie innego ukrytego pola o tej samej nazwie/id, co oryginalne pole wyboru. I jak próbowałem załadować tablicę checkbox za pomocą dokumentu.GetElemtentsByName (), możesz zgadnąć, jak sprawy się pokręciły. To dziwne.

 4
Author: Farhan Zia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-18 11:23:28

Z tego co wiem, model nie chce odgadnąć czy checkbox = true czy false, obejrzałem to ustawiając atrybut value na elemencie checkbox za pomocą jQuery przed wysłaniem formularza Tak:

 $('input[type="checkbox"]').each(function () {
       $(this).attr('value', $(this).is(':checked'));
 }); 

W ten sposób nie potrzebujesz ukrytego elementu tylko do przechowywania wartości pola wyboru.

 4
Author: BraveNewMath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-22 21:32:21

Wiem, że to pytanie zostało napisane, gdy MVC3 nie było, ale dla każdego, kto przychodzi do tego pytania i używają MVC3, możesz chcieć "poprawny" sposób, aby to zrobić.

Podczas Gdy myślę, że robiąc całość

Contains("true");

Rzecz jest świetna i czysta, i działa na wszystkich wersjach MVC, problem w tym, że nie bierze pod uwagę kultury (tak jakby to naprawdę miało znaczenie w przypadku boola).

"poprawnym" sposobem na obliczenie wartości boola, przynajmniej w MVC3, jest użycie ValueProvider.

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

Robię to na jednej z witryn mojego klienta, gdy edytuję uprawnienia:

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

Teraz, piękno tego jest to, że można go używać z prawie każdego prostego typu, A to będzie nawet poprawne w oparciu o kulturę(myśl pieniądze, dziesiętne, itp).

ValueProvider jest tym, co jest używane, gdy tworzysz swoje działania w ten sposób:

public ActionResult UpdatePermissions(bool permission_1, bool permission_2)

Ale kiedy próbujesz dynamicznie budować te listy i sprawdzać wartości, nigdy nie poznasz Id podczas kompilacji, więc musisz je przetwarzać w locie.

 4
Author: Dan VanWinkle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-24 06:34:28

Najłatwiej to zrobić...

Ustawiasz nazwę i wartość.

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

Następnie przy przesyłaniu pobieramy wartości pól wyboru i zapisujemy w tablicy int. następnie odpowiednia funkcja LinQ. To wszystko..

[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);
        }
 3
Author: kk-dev11,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-05 16:10:31

Tak samo jak odpowiedź nautic20, po prostu Użyj domyślnej listy pól wyboru wiążących model MVC o tej samej nazwie, co właściwość kolekcji string / int / enum w ViewModel. To jest to.

Ale jeden problem trzeba zwrócić uwagę. W każdym komponencie checkbox nie należy umieszczać w nim "Id", co wpłynie na powiązanie modelu MVC.

Następujący kod będzie działał dla wiązania modelu:

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

Poniższe kody nie będą wiążące dla modelu (różnica polega na tym, że przypisany jest id dla każdego checkboxa)

<% 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>
<% } %>
 3
Author: ChinaHelloWorld,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-11 17:05:00

To właśnie zrobiłem, aby stracić podwójne wartości podczas korzystania z Html.CheckBox(...

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

Z 4 polami zaznaczonymi, zaznaczonymi, zaznaczonymi, zaznaczonymi obraca się prawda, fałsz,fałsz,fałsz, fałsz, fałsz do prawda, fałsz, fałsz, prawda. just what i needed

 2
Author: Jeroen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-22 16:07:08

Może coś takiego?

bool isChecked = false;
if (Boolean.TryParse(Request.Form.GetValues(”chkHuman”)[0], out isChecked) == false)
    ModelState.AddModelError(”chkHuman”, “Nice try.”);
 0
Author: Skadoosh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-11 20:49:15

Podczas korzystania z pola wyboru HtmlHelper, wolę pracować z opublikowanymi danymi formularza checkbox jako tablica. Nie wiem dlaczego, wiem, że inne metody działają, ale myślę, że po prostu wolę traktować ciągi oddzielone przecinkami jako tablicę tak bardzo, jak to możliwe.

Więc zrobienie "sprawdzonego" lub prawdziwego testu byłoby:

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

Wykonanie fałszywego sprawdzenia byłoby:

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

Główną różnicą jest użycie GetValues jako tablicy.

 0
Author: eyesnz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-20 22:25:36

Po prostu zrób to na $(document).ready:

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

        console.log(that.id);
        that.parentElement.removeChild(that);

    }
});
 0
Author: doronAv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-10 18:19:13

Moje rozwiązanie to:

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

Więcej znajdziesz tutaj: http://www.blog.mieten.pl/2010/12/asp-net-mvc-custom-checkbox-as-solution-of-string-was-not-recognized-as-a-valid-boolean/

 0
Author: pawlom84,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-03 15:15:48

Miałem prawie ten sam Problem, ale wartość zwracana kontrolera została zablokowana innymi wartościami.

Znalazłem proste rozwiązanie, ale wydaje się nieco szorstkie.

Spróbuj wpisać Viewbag. w kontrolerze i nadaj mu nazwę podobną do Viewbag.Checkbool

Teraz przełącz się do widoku i spróbuj tego @Viewbag.Checkbool dzięki temu uzyskasz wartość z kontrolera.

Moje parametry kontrolera wyglądają tak:

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

A moje Checkbox zaktualizuje się tak:

<input id="isLive" type="checkbox" checked="@ViewBag.Value" ONCLICK="window.location.href = '/MixCategory/Anzeigen?isLive=' + isLive.checked.toString()" />
 0
Author: treborian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-17 08:15:22

Używając @ mmacaulay, wymyśliłem to dla boola:

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

Jeśli zaznaczone active = true

If unchecked active = false

 0
Author: Ravi Ram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-25 23:02:14