Pobieranie wartości pola wyboru w ASP.NET MVC 4


122

Pracuję nad aplikacją ASP.NET MVC 4. Ta aplikacja ma podstawową formę. Model mojego formularza wygląda następująco:

public class MyModel
{
    public string Name { get; set; }
    public bool Remember { get; set; }
}

W moim formularzu mam następujący HTML.

<input id="Name" name="Name" type="text" value="@Model.Name" />
<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />
<label for="Remember">&nbsp;Remember Me?</label>

Kiedy wysyłam formularz, wartość Remember w modelu jest zawsze fałszywa. Jednak właściwość Name w modelu ma wartość. Przetestowałem to, ustawiając punkt przerwania w następujący sposób:

[HttpPost]
public ActionResult MyAction(MyModel model)
{
  Console.WriteLine(model.Remember.ToString());
}

Nie mogę tego rozgryźć. Dlaczego wartość pola wyboru nie jest ustawiana?


Czy jest wysyłany z odpowiednią wartością? Czy możesz to sprawdzić za pomocą skrzypka? Nie wiem też, czy / jak wartość pola wyboru przekłada się na bool.
— shahkalpesh

Jest to publikowane w formularzu jako „włączone” lub „wyłączone”. To najwyraźniej nie jest właściwe. Zrobiłem głupią enum, żeby tego uniknąć.
— Yablargo

@Yablargo, nie potrzebujesz wyliczenia. Po prostu dodaj wartość = "true" do tagu wejściowego. I użyj ukrytego z wartością = „false”, jak pokazano poniżej.
— sympatric greg

Odpowiedzi:


213
@Html.EditorFor(x => x.Remember)

Wygeneruje:

<input id="Remember" type="checkbox" value="true" name="Remember" />
<input type="hidden" value="false" name="Remember" />

Jak to działa:

  • Jeśli checkbox pozostanie niezaznaczone, formularz przesyła tylko hiddenwartość (false)
  • Jeśli zaznaczone, wówczas forma podnosi dwa pola (fałszywych i prawdziwych) oraz zestawy MVC truedla modelu boolwłasności

<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />

To zawsze wyśle ​​wartość domyślną, jeśli jest zaznaczone.


7
Cześć, to zachowanie powoduje, że mój model nie przechodzi walidacji, ponieważ wydaje się, że nie jest w stanie wymyślić, jak zamienić [true, false] na pojedynczą wartość logiczną. Jak to obejść?
— Obi

@ObiOnuorah Jakiej konstrukcji używasz? Pomocnik CZY zakodowane na stałe znaczniki HTML?
— webdeveloper

5
Html.EditorFor lub Html.CheckBoxFor daje ten sam wynik
— Obi

3
Jeśli użyto formCollection, to ciąg zwracany dla pola wyboru jako wynik to: „true, false”. Jak to analizujesz? Czy Replace () jest jedyną opcją?
— Jo Smo

7
Jeśli dodajesz własne pola wyboru ręcznie, kluczowa część jest taka, że wartość powinna być ustawiona na „true” , w przeciwnym razie domyślna wartość zwracana przez formularz to „on”, a „on” nie może być przypisana do wartości bool który potrzebuje prawda / fałsz. (Możesz zobaczyć błąd weryfikacji, że wartość „on” jest nieprawidłowa dla pola ).
— Greg,

69

Ponieważ używasz Model.Name do ustawiania wartości. Zakładam, że przekazujesz pusty model widoku do widoku.

Zatem wartość Remember to false i ustawia wartość elementu checkbox na false. Oznacza to, że po zaznaczeniu tego pola wyboru, w formularzu wysyłasz wartość „false”. Jeśli go nie wybierzesz, nie zostanie opublikowany, więc model domyślnie ma wartość false. Dlatego w obu przypadkach widzisz fałszywą wartość.

Wartość jest przekazywana tylko wtedy, gdy zaznaczysz pole wyboru. Aby zrobić pole wyboru w MVC użyj

@Html.CheckBoxFor(x => x.Remember)

lub jeśli nie chcesz wiązać modelu z widokiem.

@Html.CheckBox("Remember")

Mvc robi magię z ukrytym polem, aby zachować wartości, gdy nie są wybrane.

Edytuj, jeśli naprawdę masz awersję do tego i chcesz samodzielnie wygenerować element, możesz to zrobić.

<input id="Remember" name="Remember" type="checkbox" value="true" @(Model.Remember ? "checked=\"checked\"" : "") />

2
@Html.CheckboxForKod powinien być rzeczywiście@Html.CheckBoxFor
— fujiiface

Tylko szybki, jak @(Model.Remember ? "checked=\"checked\"" : "")użyłbyś przycisku radiowego? czy nie jest to możliwe
— Izzy

Dzięki tej opcji są po prostu zmieniając kod HTML bezpośrednio, przycisk radiowy jest tylko type="radio"i wybierając ten, który chcesz wybrany w HTML jest taka sama jak powyżej checked="checked". Różnica polega na tym, że będziesz mieć wiele <input />elementów o tej samej nazwie. Musisz dowiedzieć się, do którego z nich zastosować dodatkowy kod HTML.
— Dan Saltmer

@Html.CheckBoxFor(x => x.Remember)to zadziałało dla mnie
— JustLearning

15

Używaj tylko tego

$("input[type=checkbox]").change(function () {
    if ($(this).prop("checked")) {
        $(this).val(true);
    } else {
        $(this).val(false);
    }
});

Lub:$(this).val($(this).is(":checked"));
— Norman

5

Zamiast

 <input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />

posługiwać się:

 @Html.EditorFor(x => x.Remember)

To da ci pole wyboru specjalnie dla Zapamiętaj


4

OK, pole wyboru jest trochę dziwne. Gdy używasz pomocnika HTML, generuje on dwa pola wyboru w znaczniku, a oba z nich są przekazywane jako para nazwa-wartość IEnumerable, jeśli jest zaznaczona.

Jeśli nie jest zaznaczone na znaczniku, zostanie przekazane tylko ukryte wejście, które ma wartość false.

Na przykład na znacznikach masz:

      @Html.CheckBox("Chbxs") 

I w akcji kontrolera (upewnij się, że nazwa jest zgodna z nazwą parametru pola wyboru na kontrolerze):

      public ActionResult Index(string param1, string param2,
      string param3, IEnumerable<bool> Chbxs)

Następnie w kontrolerze możesz zrobić takie rzeczy jak:

      if (Chbxs != null && Chbxs.Count() == 2)
        {
            checkBoxOnMarkup = true;
        }
        else
        {
            checkBoxOnMarkup = false;
        }

Wiem, że to nie jest eleganckie rozwiązanie. Mam nadzieję, że ktoś tutaj może udzielić kilku wskazówek.


3

Aby przekonwertować wartość zwróconą z pola wyboru w formularzu na właściwość logiczną, użyłem ValueProviderResult w konwerterze kompilacji w niestandardowym ModelBinder.

ValueProviderResult cbValue = bindingContext.ValueProvider.GetValue("CheckBoxName");
bool value = (bool)cbValue.ConvertTo(typeof(bool));

3

Jeśli pracujesz z FormCollection, a nie z modelem, przypisanie może być tak proste, jak:

MyModel.Remember = fields["Remember"] != "false";

2

Napotkałem podobny problem i udało mi się odzyskać wartość pola wyboru, używając pola wyboru, ukrytego dla i małego JQuery:

@Html.CheckBox("isPreferred", Model.IsPreferred)
@Html.HiddenFor(m => m.IsPreferred)

<script>

    $("#isPreferred").change(function () {

        $("#IsPreferred").val($("#isPreferred").val());

    })

</script>

2

To był duży ból i wydaje się, że powinno być prostsze. Oto moja konfiguracja i rozwiązanie.

Używam następującego pomocnika HTML:

@Html.CheckBoxFor(model => model.ActiveFlag)

Następnie w administratorze sprawdzam sposób zbierania i przetwarzania formularzy:

bool activeFlag = collection["ActiveFlag"] == "false" ? false : true;
[modelObject].ActiveFlag = activeFlag;

Zgoda, zrobiłem to jeszcze krócej, ponieważ user.IsActive = fc["IsActive"] != "false";nadal czuję się brudny, robiąc na nim porównanie ciągów.
— WildJoe

1

Właśnie wpadłem na to (nie mogę uwierzyć, że się nie włącza / wyłącza!)

W każdym razie!

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

Opublikuje wartość „on” lub „off”.

To NIE BĘDZIE wiązało się z wartością logiczną, ale możesz zrobić to głupie obejście!

 public class MyViewModel
 {
     /// <summary>
     /// This is a really dumb hack, because the form post sends "on" / "off"
     /// </summary>                    
     public enum Checkbox
     {
        on = 1,
        off = 0
     }
     public string Name { get; set; }
     public Checkbox Checked { get; set; }
}

1
@Html.EditorFor(x => x.ShowComment)


$(function () {
        // set default value to control on document ready instead of 'on'/'off' 
        $("input[type='checkbox'][name='ShowComment']").val(@Model.ShowComment.ToString().ToLower());
    });

    $("#ShowComment").change(function() {
        // this block sets value to checkbox control for "true" / "false"

        var chkVal = $("input[type='checkbox'][name='ShowComment']").val();
        if (chkVal == 'false') $("input[type='checkbox'][name='ShowComment']").val(true);
        else $("input[type='checkbox'][name='ShowComment']").val(false);

    });

3
Witaj Surendran i witaj w Stack Overflow. Dołączając kod, sformatuj go, aby był czytelny. Ale co ważniejsze, ważne jest, aby wyjaśnić, dlaczego dołączony kod odpowiada na pytanie PO.
— Alex A.

1

Dla MVC przy użyciu Model. Model:

public class UserInfo
{
    public string UserID { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
    public bool RememberMe { get; set; }
}

HTML:

<input type="checkbox" value="true" id="checkbox1" name="RememberMe" checked="@Model.RememberMe"/>
<label for="checkbox1"></label>

W funkcji [HttpPost] możemy pobrać jej właściwości.

[HttpPost]
public ActionResult Login(UserInfo user)
{
   //...
   return View(user);
}

1

Jeśli naprawdę chcesz używać zwykłego HTML (z jakiegokolwiek powodu), a nie wbudowanych rozszerzeń HtmlHelper, możesz to zrobić w ten sposób.

Zamiast

<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />

spróbuj użyć

<input id="Remember" name="Remember" type="checkbox" value="true" @(Model.Remember ? "checked" : "") />

Pola wyboru w HTML działają tak, że gdy są zaznaczone, wysyłają wartość, a gdy nie są zaznaczone, w ogóle nic nie wysyłają (co spowoduje, że ASP.NET MVC powróci do domyślnej wartości pole, false ). Ponadto wartość pola wyboru w HTML może być dowolna, a nie tylko prawda / fałsz, więc jeśli naprawdę chcesz, możesz nawet użyć pola wyboru dla pola ciągu w swoim modelu.

Jeśli używasz wbudowanego, w Html.RenderCheckboxrzeczywistości wyprowadza dwa wejścia: pole wyboru i ukryte pole, dzięki czemu wysyłana jest fałszywa wartość, gdy pole wyboru nie jest zaznaczone (a nie tylko nic). Może to spowodować nieoczekiwane sytuacje, takie jak ta:


0

Dla wielu pól wyboru o tej samej nazwie ... Kod do usuwania niepotrzebnego fałszu:

List<string> d_taxe1 = new List<string>(Request.Form.GetValues("taxe1"));
d_taxe1 = form_checkbox.RemoveExtraFalseFromCheckbox(d_taxe1);

Funkcjonować

public class form_checkbox
{

    public static List<string> RemoveExtraFalseFromCheckbox(List<string> val)
    {
        List<string> d_taxe1_list = new List<string>(val);

        int y = 0;

        foreach (string cbox in val)
        {

            if (val[y] == "false")
            {
                if (y > 0)
                {
                    if (val[y - 1] == "true")
                    {
                        d_taxe1_list[y] = "remove";
                    }
                }

            }

            y++;
        }

        val = new List<string>(d_taxe1_list);

        foreach (var del in d_taxe1_list)
            if (del == "remove") val.Remove(del);

        return val;

    }      



}

Użyj tego :

int x = 0;
foreach (var detail in d_prix){
factured.taxe1 = (d_taxe1[x] == "true") ? true : false;
x++;
}

0
public ActionResult Index(string username, string password, string rememberMe)
{
   if (!string.IsNullOrEmpty(username))
   {
      bool remember = bool.Parse(rememberMe);
      //...
   }
   return View();
}

0

Modyfikuj Zapamiętaj w ten sposób

public class MyModel
{
    public string Name { get; set; }
    public bool? Remember { get; set; }
}

Użyj wartości null bool w kontrolerze i przejdź do wartości false dla wartości null w ten sposób

[HttpPost]
public ActionResult MyAction(MyModel model)
{
    model.Remember = model.Remember ?? false;
    Console.WriteLine(model.Remember.ToString());
}

0

W moim przypadku nie ustawiałem właściwości modelu „Remember” w metodzie get. Sprawdź logikę w kontrolerze. Możesz robić to samo. Mam nadzieję, że ta pomoc!


0

Przeczytałem inne odpowiedzi i nie do końca udało mi się to zadziałać - więc oto rozwiązanie, które znalazłem.

Mój formularz używa Html.EditorFor(e => e.Property)do wygenerowania pola wyboru, a użycie FormCollectionw kontrolerze przekazuje wartość ciągu 'true,false'w kontrolerze.

Kiedy obsługuję wyniki, używam pętli do przechodzenia między nimi - używam również InfoPropertyinstancji do reprezentowania bieżącej wartości modelu, która jest oceniana z formularza.

Zamiast tego po prostu sprawdzam, czy zwracany ciąg zaczyna się od słowa, 'true'a następnie ustawiam zmienną boolowską na truei przekazuję ją do modelu zwracanego.

if (KeyName.EndsWith("OnOff"))
{
    // set on/off flags value to the model instance
    bool keyTrueFalse = false;
    if(values[KeyName].StartsWith("true"))
    {
        keyTrueFalse = true;
    }
    infoProperty.SetValue(processedInfo, keyTrueFalse);
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.