Pergunta

Atenção: Esta questão é mais de nove anos de idade

A sua melhor opção é procurar perguntas mais recentes, ou para procurar as respostas abaixo procurando sua versão específica do MVC, como muitas respostas aqui são obsoletos agora.

Se você não encontrar uma resposta que funciona para a sua versão, certifique-se a resposta contém a versão do MVC você está usando.
(A pergunta original começa abaixo)


Este parece um pouco bizarro para mim, mas tanto quanto eu posso dizer, isso é como fazê-lo.

Eu tenho uma coleção de objetos, e eu quero que os usuários selecionem um ou mais deles. Isto diz-me "formulário com caixas de seleção." Meus objetos não têm qualquer conceito de "selecionados" (eles são POCO rudimentar é formado por deserializing uma chamada WCF). Então, eu faço o seguinte:

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

Do ponto de vista:

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

E, no controlador, esta é a única maneira que eu posso ver para descobrir o que os objetos que o usuário selecionado:

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

Sua louca, em primeiro lugar, e em segundo lugar, para aqueles itens que o usuário verificados, o FormCollection lista seu valor como "verdadeiro falso" em vez de apenas verdadeiro.

Obviamente, eu estou faltando alguma coisa. Acho que este é construído com a idéia em mente que os objetos na coleção que são postas em prática dentro do formulário html são atualizadas com UpdateModel() ou através de um ModelBinder.

Mas meus objetos não estão configurados para isso; Isso significa que esta é a única maneira? Existe outra maneira de fazê-lo?

Foi útil?

Solução

Html.Checkbox está fazendo algo estranho - se você visualizar fonte na página resultante, você verá que há um <input type="hidden" /> sendo gerado ao lado de cada caixa de seleção, o que explica os valores "verdadeiro falso" você está vendo para cada elemento do formulário.

Tente este, que definitivamente funciona em ASP.NET MVC Beta porque eu apenas tentei-lo.

Coloque este na vista em vez de usar 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" />
<%}%>

As suas caixas são todos chamados selectedObjects, eo value de cada caixa é o GUID do objeto correspondente.

Em seguida, enviar para a ação seguinte controlador (ou algo semelhante que faz algo útil em vez de Response.Write ())

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

Este exemplo vai apenas escrever os GUIDs das caixas você verificados; ASP.NET MVC mapeia os valores GUID das caixas de seleção marcadas para o parâmetro Guid[] selectedObjects para você, e ainda analisa as cordas da coleção Request.Form em objetos GUID instanciado, que acho que é bastante agradável.

Outras dicas

HtmlHelper adiciona uma entrada escondida para notificar o controlador sobre o status desmarcada. Portanto, para ter o status marcada correta:

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

Caso você esteja se perguntando por que eles colocaram um campo escondido com o mesmo nome que a caixa de seleção a razão é a seguinte:

Comentário do código fonte MVCBetaSource \ MVC \ src \ MvcFutures \ Mvc \ ButtonsAndLinkExtensions.cs

Render um <input type="hidden".../> adicional para caixas de seleção. Isso resolve cenários onde caixas de seleção desmarcadas não são enviados em o pedido. O envio de uma entrada escondida torna possível saber que o checkbox estava presente na página quando o pedido foi apresentado.

Eu acho que por trás das cenas que eles precisam saber isso para a ligação com os parâmetros sobre os métodos de ação do controlador. Você poderia, então, ter um tri-state boolean Suponho (ligado a um parâmetro bool anulável). Eu não tentei isso, mas eu estou esperando que isso é o que eles fizeram.

Você também deve usar <label for="checkbox1">Checkbox 1</label> porque as pessoas, em seguida, pode clicar no texto do rótulo, bem como a própria caixa. É também mais fácil de estilo e, pelo menos no IE ele será destacado quando você guia através de controles da página.

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

Este não é apenas um 'oh, eu poderia fazê-lo' coisa. É uma experiência melhoria significativa do usuário. Mesmo que nem todos os usuários sabem que podem clicar no rótulo muitos vontade.

Eu sou nenhum surpreso dessas respostas usou o construído em MVC apresenta para isso.

Eu escrevi um post sobre este aqui , que mesmo na verdade liga os rótulos para a caixa de seleção. Eu usei o EditorTemplate pasta para alcançar este objetivo de forma limpa e modular.

Você vai simplesmente acabar com um novo arquivo na pasta EditorTemplate parecida com esta:

@model SampleObject

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

no seu ponto de vista real, não haverá necessidade de laço isso, basta uma linha de código:

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

Visite o meu blog para mais detalhes.

Aqui está o que eu tenho feito.

Ver:


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

Controlador:


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

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

Eu encontrei o código HTML. * Métodos auxiliares não tão úteis em alguns casos, e que eu era melhor fazer isso na planície velho HTML. Esta sendo um deles, o outro que vem à mente é botões de rádio.

Edit:. Esta é a Preview 5, obviamente, YMMV entre as versões

Eles parecem estar optando por ler apenas o primeiro valor, de modo que este é "true" quando a caixa está marcada, e "falso" quando apenas o valor escondido está incluído. Isso é facilmente obtida com um código como este:

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

@Dylan Beattie Great Encontrar !!! Agradeço-lhe muito. Para expandir ainda mais, esta técnica também funciona perfeito com a abordagem Model View. MVC é tão legal, é inteligente o suficiente para ligar uma série de Guids a uma propriedade com o mesmo nome do objeto Modelo vinculado à View. Exemplo:

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

Ver:

<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" />
<%}%>                    

Controlador:

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

Qualquer pessoa familiarizada com a filosofia Model View se alegrarão, isso funciona como um campeão!

Eu também gostaria de salientar que você pode nomear cada caixa um nome diferente, e ter essa parte do nome dos parâmetros actionresults.

Exemplo,

Ver:

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

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

Controlador:

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

Os valores da visão são passados ??para a ação uma vez que os nomes são os mesmos.

Eu sei que esta solução não é ideal para o seu projeto, mas eu pensei que eu iria jogar a idéia lá fora.

<input type = "checkbox" name = "checkbox1" /> <label> Check to say hi.</label>

A partir do Controlador:

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

         var s = fc["checkbox1"];

         if (s == "on")
         {
             string x = "Hi";
         }
    }

Este problema está acontecendo na versão 1.0 também. Html.Checkbox () faz com que um outro campo escondido para ser adicionado com o mesmo nome / id como de sua caixa originais. E como eu estava tentando carregar até uma matriz caixa de verificação usando document.GetElemtentsByName (), você pode adivinhar como as coisas estavam ficando confuso. É uma bizarra.

Desde que eu possa reunir, o modelo não quer adivinhar se verificado = verdadeiro ou falso, eu tenho em torno isso definindo um atributo de valor no elemento caixa com jQuery antes de submeter o formulário como este:

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

Desta forma, você não precisa de um elemento escondido apenas para armazenar o valor da caixa de seleção.

Eu sei que esta questão foi escrito quando MVC3 não estava fora, mas para quem vem a esta questão e estão usando MVC3, você pode querer a maneira "correta" para fazer isso.

Enquanto eu acho que fazendo todo

Contains("true");

coisa é grande e limpo, e funciona em todas as versões MVC, o problema é que ele não leva em conta a cultura (como se realmente importa no caso de um bool).

A maneira "correta" para descobrir o valor de um booleano, pelo menos em MVC3, é usar o ValueProvider.

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

Eu faço isso em um dos locais do meu cliente quando eu permissões de edição:

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

Agora, a beleza desta é que você pode usar isso com praticamente qualquer tipo simples, e vai mesmo ser correto com base na Cultura (acho que o dinheiro, decimais, etc).

O ValueProvider é o que é usado quando você formar suas ações como esta:

public ActionResult UpdatePermissions(bool permission_1, bool permission_2)

mas quando você está tentando construir dinamicamente estas listas e verificar os valores, você nunca vai saber o Id em tempo de compilação, então você tem que processá-los em tempo real.

A maneira mais fácil de fazer é tão ...

Você define o nome e valor.

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

Em seguida, sobre o envio de agarrar os valores das caixas de seleção e salvar em uma matriz int. Então, a função LinQ apropriado. É isso ..

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

Mesmo que a resposta do nautic20, simplesmente usar o modelo padrão MVC lista caixa de ligação com o mesmo nome de uma propriedade de coleção de corda / int / enum em ViewModel. Isso é que é.

Mas uma necessidade questão de salientar. Em cada componente caixa de seleção, você não deve colocar "Id" em que ela irá afectar a ligação modelo MVC.

A seguir código irá funcionar para o modelo de ligação:

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

seguintes códigos não vai ligar ao modelo (diferença aqui é atribuído id para cada caixa)

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

este é o que eu fiz a perder os valores duplas ao usar o Html.Checkbox (...

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

com 4 caixas marcada, desmarcada, sem controle, verifiquei voltas verdadeiro, falso, falso, falso, verdadeiro, falso para dentro verdadeiro, falso, falso, verdadeiro. apenas o que eu precisava

Como sobre algo assim?

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

Ao usar o HtmlHelper caixa, eu prefiro muito mais para trabalhar com os dados do formulário caixa postado como um array. Eu realmente não sei por que, eu sei que os outros métodos de trabalho, mas acho que simplesmente preferem vírgula deleite separados cordas como uma matriz, tanto quanto possível.

Então, fazendo um 'checada' ou verdadeiro teste seria:

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

Fazendo uma falsa verificação seria:

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

A principal diferença é a utilização de GetValues como esta retorna como uma matriz.

Apenas fazer isso em $(document).ready:

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

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

    }
});

A minha solução é:

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

Mais você pode encontrar aqui: http://www.blog.mieten.pl/2010/12/asp-net-mvc-custom-checkbox-as-solution-of-string-was-not-recognized- as-a-valid-boolean /

Eu tinha quase o mesmo problema, mas o valor de retorno do meu controlador foi bloqueada com outros valores.

encontrou uma solução simples, mas parece um pouco rústica.

Tente digitar Viewbag. em seu controlador e agora você dar-lhe um nome como Viewbag.Checkbool

Agora, mude para a vista e experimentar esta @Viewbag.Checkbool com isso, você receberá o valor fora do Controller.

Meu Controlador Parâmetros parecido com este:

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

e minha Caixa de seleção irá atualizar como este:

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

Usando @mmacaulay, eu vim com isso para bool:

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

Se estiver marcada active = true

Se desmarcada ativo = false

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top