Obtendo o valor da caixa de seleção na ASP.NET MVC 4

122

Estou trabalhando em um aplicativo ASP.NET MVC 4. Este aplicativo possui um formulário básico. O modelo do meu formulário se parece com o seguinte:

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

No meu formulário, tenho o seguinte 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>

Quando eu posto o formulário, o valor Lembrar no modelo é sempre falso. No entanto, a propriedade Name no modelo tem um valor. Eu testei isso definindo um ponto de interrupção no seguinte:

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

Eu não consigo entender. Por que o valor Checkbox não está sendo definido?

JQuery Mobile
fonte
É postado com o valor adequado? Você pode verificar isso usando o fiddler? Além disso, não sei se / como o valor da caixa de seleção se traduz em bool.
shahkalpesh
Isso é postado como "ativado" ou "desativado" no formulário. Isso aparentemente não liga direito. Fiz uma enum idiota para evitar isso.
Yablargo
@Yablargo, você não precisa do enum. Basta adicionar value = "true" à tag de entrada. E use um oculto com valor = "false", conforme mostrado abaixo.
sympatric greg

Respostas:

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

Irá gerar:

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

Como funciona:

  • Se checkboxpermanecer desmarcado, o formulário enviará apenas o hiddenvalor (falso)
  • Se marcado, o formulário envia dois campos (falso e verdadeiro) e conjuntos MVC truepara a boolpropriedade do modelo

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

Isso sempre enviará o valor padrão, se marcado.

webdeveloper
fonte
7
Olá, isso faz com que meu modelo falhe nas validações, pois não parece ser capaz de descobrir como transformar [verdadeiro, falso] em um único valor booleano. Como você contorna isso?
Obi
@ObiOnuorah Que construção você está usando? Helper OU marcação de HTML embutida em código?
webdeveloper de
5
Html.EditorFor ou Html.CheckBoxFor fornecem o mesmo resultado
Obi
3
Se formCollection for usado, então a string retornada para a caixa de seleção como resultado é: "true, false". Como você analisa isso? Replace () é a única opção?
Jo Smo
7
Se você estiver adicionando suas próprias caixas de seleção manualmente, a parte principal é que o valor deve ser definido como "true" , caso contrário, o valor padrão retornado pelo formulário será "on" e "on" não pode ser vinculado a um bool que precisa de verdadeiro / falso. (Você pode ver um erro de validação de que o valor "on" não é válido para o campo .)
Greg
69

Já que você está usando Model.Name para definir o valor. Suponho que você está passando um modelo de visão vazio para a visão.

Portanto, o valor para Lembrar é falso e define o valor no elemento checkbox como falso. Isso significa que, quando você marca a caixa de seleção, está postando o valor "falso" com o formulário. Quando você não o seleciona, ele não é postado, portanto, o padrão do modelo é falso. É por isso que você está vendo um valor falso em ambos os casos.

O valor só é passado quando você marca a caixa de seleção. Para marcar uma caixa de seleção no Mvc, use

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

ou se você não deseja vincular o modelo à vista.

@Html.CheckBox("Remember")

O Mvc faz mágica com um campo oculto para persistir os valores quando eles não são selecionados.

Edite, se você realmente tem aversão a fazer isso e deseja gerar o elemento sozinho, você pode fazer.

<input id="Remember" name="Remember" type="checkbox" value="true" @(Model.Remember ? "checked=\"checked\"" : "") />
Dan Saltmer
fonte
2
O @Html.CheckboxForcódigo deveria ser@Html.CheckBoxFor
fujiiface
Apenas uma rápida: como você usaria @(Model.Remember ? "checked=\"checked\"" : "")em um botão de rádio? ou isso não é possível
Izzy
Com essa opção você está apenas manipulando o HTML diretamente, basta um botão de rádio type="radio", e selecionar o que deseja selecionar no HTML é o mesmo que acima checked="checked",. A diferença é que você terá vários <input />elementos com o mesmo nome. Você precisa descobrir em qual deles aplicar o HTML extra.
Dan Saltmer de
@Html.CheckBoxFor(x => x.Remember)isso funcionou para mim
JustLearning
15

Use apenas este

$("input[type=checkbox]").change(function () {
    if ($(this).prop("checked")) {
        $(this).val(true);
    } else {
        $(this).val(false);
    }
});
Bekir Topuz
fonte
Ou:$(this).val($(this).is(":checked"));
Norman
5

Ao invés de

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

usar:

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

Isso lhe dará uma caixa de seleção específica para Lembrar

Robert
fonte
4

Ok, a caixa de seleção é um pouco estranha. Quando você usa o auxiliar Html, ele gera duas entradas de caixa de seleção na marcação e ambas são passadas como um par nome-valor de IEnumerable se estiver marcado.

Se não estiver marcada na marcação, ela será passada apenas na entrada oculta que possui valor false.

Por exemplo, na marcação você tem:

      @Html.CheckBox("Chbxs") 

E na ação do controlador (certifique-se de que o nome corresponda ao nome do parâmetro da caixa de seleção no controlador):

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

Então, no controlador, você pode fazer algumas coisas como:

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

Eu sei que esta não é uma solução elegante. Espero que alguém aqui possa dar algumas dicas.

Yini
fonte
3

Para converter um valor retornado de uma caixa de seleção em um formulário em uma propriedade booleana, usei o conversor ValueProviderResult em build em um ModelBinder personalizado.

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

Se estiver trabalhando com FormCollection em vez de model, a atribuição pode ser tão simples como:

MyModel.Remember = fields["Remember"] != "false";
Aaron Carter
fonte
2

Eu encontrei um problema semelhante e consegui obter o valor da caixa de seleção de volta usando uma caixa de seleção, hiddenfor e pouco JQuery assim:

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

<script>

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

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

    })

</script>
John Meyer
fonte
2

Isso tem sido uma grande dor e parece que deveria ser mais simples. Aqui está minha configuração e solução.

Estou usando o seguinte auxiliar de HTML:

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

Então, no controlador, estou verificando a coleta de formulários e processando de acordo:

bool activeFlag = collection["ActiveFlag"] == "false" ? false : true;
[modelObject].ActiveFlag = activeFlag;
Fujiiface
fonte
Concordo, eu deixei isso ainda mais curto, pois user.IsActive = fc["IsActive"] != "false";ainda me sinto sujo por fazer uma comparação de cordas nele.
WildJoe
1

Acabei de encontrar isso (não acredito que não liga / desliga!)

Enfim!

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

Postará um valor de "on" ou "off".

Isso NÃO vai vincular a um booleano, mas você pode fazer esta solução alternativa boba!

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

    });
Surendran
fonte
3
Olá Surendran e bem-vindo ao Stack Overflow. Ao incluir o código, formate-o para facilitar a leitura. Mas, mais importante, é crucial explicar por que o código incluído aborda a questão do OP.
Alex A.
1

Para o MVC usando Model. Modelo:

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>

Na função [HttpPost], podemos obter suas propriedades.

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

Se você realmente deseja usar HTML simples (por qualquer motivo) e não as extensões HtmlHelper embutidas, você pode fazer isso desta forma.

Ao invés de

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

tente usar

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

As entradas da caixa de seleção em HTML funcionam de forma que, quando marcadas, enviam o valor, e quando não são marcadas, não enviam nada (o que fará com que a ASP.NET MVC volte ao valor padrão do campo, false ). Além disso, o valor da caixa de seleção em HTML pode ser qualquer coisa não apenas verdadeiro / falso, então, se você realmente quiser, pode até usar uma caixa de seleção para um campo de string em seu modelo.

Se você usar o embutido Html.RenderCheckbox, ele realmente produzirá duas entradas: caixa de seleção e um campo oculto para que um valor falso seja enviado quando a caixa de seleção for desmarcada (não apenas nada). Isso pode causar algumas situações inesperadas, como esta:

Tom Pažourek
fonte
0

Para várias caixas de seleção com o mesmo nome ... Código para remover falso desnecessário:

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

Função

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;

    }      



}

Use-o :

int x = 0;
foreach (var detail in d_prix){
factured.taxe1 = (d_taxe1[x] == "true") ? true : false;
x++;
}
Pascal Carmoni
fonte
0
public ActionResult Index(string username, string password, string rememberMe)
{
   if (!string.IsNullOrEmpty(username))
   {
      bool remember = bool.Parse(rememberMe);
      //...
   }
   return View();
}

fonte
0

Modificar Lembre-se assim

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

Use bool anulável no controlador e fallback para falso em nulo como este

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

No meu caso, não estava definindo a propriedade de modelo "Lembrar" no método get. Verifique sua lógica no controlador. Você pode estar fazendo o mesmo. Espero esta ajuda!

Nour Lababidi
fonte
0

Eu li as outras respostas e não estava fazendo funcionar - então aqui está a solução que encontrei.

Meu formulário usa o Html.EditorFor(e => e.Property)para gerar a caixa de seleção, e usando FormCollectionno controlador, isso passa um valor de string 'true,false'no controlador.

Quando estou lidando com os resultados, uso um loop para percorrê-los - também uso uma InfoPropertyinstância para representar o valor do modelo atual que está sendo avaliado no formulário.

Então, em vez disso, apenas verifico se a string retornada começa com a palavra 'true'e, em seguida, defino uma variável booleana para truee a passo para o modelo de retorno.

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);
}
C Gil
fonte