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.