Domanda

Attenzione: questa domanda ha più di nove anni!

La tua migliore opzione è quella di cercare nuove domande o cercare le risposte di seguito cercando la tua versione specifica di MVC, dato che molte risposte qui sono ormai obsolete.

Se trovi una risposta che funziona per la tua versione, assicurati che la risposta contenga la versione di MVC che stai utilizzando.
(La domanda originale inizia di seguito)


Questo mi sembra un po 'strano, ma per quanto posso dire, è così che lo fai.

Ho una raccolta di oggetti e voglio che gli utenti selezionino uno o più di essi. Questo mi dice & Quot; modulo con caselle di controllo. & Quot; I miei oggetti non hanno alcun concetto di & Quot; selezionato & Quot; (sono rudimentali POCO formati deserializzando una chiamata wcf). Quindi, faccio quanto segue:

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

Nella vista:

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

E, nel controller, questo è l'unico modo che posso vedere per capire quali oggetti l'utente ha verificato:

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

In primo luogo è strano, e in secondo luogo, per quegli elementi controllati dall'utente, FormCollection elenca il suo valore come " true false " piuttosto che semplicemente vero.

Ovviamente, mi manca qualcosa. Penso che questo sia costruito pensando all'idea che gli oggetti nella raccolta su cui si agiscono all'interno del modulo HTML vengono aggiornati usando UpdateModel() o tramite un ModelBinder.

Ma i miei oggetti non sono impostati per questo; significa che questo è l'unico modo? C'è un altro modo per farlo?

È stato utile?

Soluzione

Html.CheckBox sta facendo qualcosa di strano: se visualizzi la sorgente sulla pagina risultante, vedrai che viene generato un <input type="hidden" /> accanto a ciascuna casella di controllo, il che spiega il " true false " valori visualizzati per ogni elemento del modulo.

Prova questo, che sicuramente funziona su ASP.NET MVC Beta perché l'ho appena provato.

Metti questo nella vista invece di usare 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" />
<%}%>

Le tue caselle di controllo sono tutte chiamate selectedObjects e il value di ogni casella è il GUID dell'oggetto corrispondente.

Quindi pubblica la seguente azione del controller (o qualcosa di simile che fa qualcosa di utile invece di Response.Write ())

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

Questo esempio scriverà semplicemente i GUID delle caselle selezionate; ASP.NET MVC esegue il mapping dei valori GUID delle caselle di controllo selezionate nel parametro Guid[] selectedObjects per te e analizza persino le stringhe dalla raccolta Request.Form in oggetti GUID istanti, che ritengo piuttosto carino.

Altri suggerimenti

HtmlHelper aggiunge un input nascosto per notificare al controller lo stato Non controllato. Quindi, per avere lo stato corretto verificato:

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

Nel caso ti stia chiedendo PERCHÉ hanno inserito un campo nascosto con lo stesso nome della casella di controllo, il motivo è il seguente:

Commento dal codice sorgente MVCBetaSource \ MVC \ src \ MvcFutures \ Mvc \ ButtonsAndLinkExtensions.cs

  

Rendering di un <input type="hidden".../> aggiuntivo per le caselle di controllo.   Questo risolve gli scenari in cui   le caselle di controllo non selezionate non vengono inviate   la richiesta. Invio di un input nascosto   rende possibile sapere che il   la casella di controllo era presente sulla pagina quando   la richiesta è stata inviata.

Immagino che dietro le quinte debbano saperlo per legarsi ai parametri sui metodi di azione del controller. Potresti quindi avere un booleano tri-stato suppongo (associato a un parametro bool nullabile). Non l'ho provato ma spero che sia quello che hanno fatto.

Dovresti anche usare <label for="checkbox1">Checkbox 1</label> perché le persone possono fare clic sul testo dell'etichetta e sulla casella stessa. È anche più facile da modellare e almeno in IE verrà evidenziato quando si sfogliano i controlli della pagina.

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

Questa non è solo una cosa "oh, potrei farlo". È un significativo miglioramento dell'esperienza utente. Anche se non tutti gli utenti sanno di poter fare clic sull'etichetta, molti lo faranno.

Sono sorpreso che nessuna di queste risposte abbia utilizzato le funzionalità MVC integrate per questo.

Ho scritto un post sul blog su questo qui , che collega effettivamente le etichette alla casella di controllo. Ho usato la cartella EditorTemplate per farlo in modo pulito e modulare.

Finirai semplicemente con un nuovo file nella cartella EditorTemplate che assomiglia a questo:

@model SampleObject

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

nella tua vista reale, non sarà necessario eseguire questo ciclo, semplicemente 1 riga di codice:

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

Visita il mio post sul blog per maggiori dettagli.

Ecco cosa ho fatto.

Visualizza:


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

Controller:


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

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

Ho trovato i metodi di supporto Html. * non così utili in alcuni casi, e che avrei fatto meglio a farlo nel semplice vecchio HTML. Essendo uno di questi, l'altro che viene in mente sono i pulsanti di opzione.

Modifica: questo è nell'anteprima 5, ovviamente YMMV tra le versioni.

Sembrano scegliere di leggere solo il primo valore, quindi questo è " true " quando la casella è selezionata e " false " quando è incluso solo il valore nascosto. Questo è facilmente recuperabile con un codice come questo:

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

@Dylan Beattie Great Find !!! Ti ringrazio molto Per espandere ulteriormente, questa tecnica funziona perfettamente anche con l'approccio Visualizza modello. MVC è così bello, è abbastanza intelligente da associare una matrice di Guide a una proprietà con lo stesso nome dell'oggetto Modello associato alla Vista. Esempio:

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

Visualizza:

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

Controller:

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

Chiunque abbia familiarità con la filosofia View Model gioirà, questo funziona come un Champ!

Vorrei anche sottolineare che è possibile assegnare un nome diverso a ciascuna casella di controllo e che tale nome faccia parte dei parametri di actionresults.

Esempio

Visualizza:

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

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

Controller:

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

I valori della vista vengono passati all'azione poiché i nomi sono gli stessi.

So che questa soluzione non è l'ideale per il tuo progetto, ma ho pensato di lanciare l'idea là fuori

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

Dal controller:

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

         var s = fc["checkbox1"];

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

Questo problema si verifica anche nella versione 1.0. Html.Checkbox () fa sì che un altro campo nascosto venga aggiunto con lo stesso nome / id della tua casella di controllo originale. E mentre stavo provando a caricare un array di checkbox usando document.GetElemtentsByName (), puoi indovinare come le cose venivano incasinate. È un bizzarro.

Da quello che posso raccogliere, il modello non vuole indovinare se controllato = vero o falso, ho aggirato questo impostando un attributo valore sull'elemento checkbox con jQuery prima di inviare il modulo in questo modo:

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

In questo modo, non è necessario un elemento nascosto solo per memorizzare il valore della casella di controllo.

So che questa domanda è stata scritta quando MVC3 non è uscito, ma per chiunque arrivi a questa domanda e stia utilizzando MVC3, potresti desiderare il " correct " modo per farlo.

Mentre penso che faccia tutto

Contains("true");

la cosa è ottima e pulita e funziona su tutte le versioni di MVC, il problema è che non tiene conto della cultura (come se davvero importasse nel caso di un bool).

Il " corretto " il modo per capire il valore di un bool, almeno in MVC3, è usare ValueProvider.

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

Faccio questo in uno dei siti dei miei clienti quando modifico i permessi:

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

Ora, la bellezza di questo è che puoi usarlo praticamente con qualsiasi tipo semplice, e sarà persino corretto in base alla Cultura (pensa a soldi, decimali, ecc.)

ValueProvider è ciò che viene utilizzato quando si formano le tue azioni in questo modo:

public ActionResult UpdatePermissions(bool permission_1, bool permission_2)

ma quando stai cercando di costruire dinamicamente questi elenchi e controllare i valori, non conoscerai mai l'ID al momento della compilazione, quindi devi elaborarli al volo.

Il modo più semplice per farlo è così ...

Hai impostato il nome e il valore.

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

Quindi, inviando, prendi i valori delle caselle di controllo e salva in un array int. quindi la funzione LinQ appropriata. Questo è tutto ..

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

Come per la risposta di nautic20, basta semplicemente usare l'elenco di controllo associato al modello predefinito MVC con lo stesso nome di una proprietà collection di string / int / enum in ViewModel. Questo è tutto.

Ma è necessario sottolineare un problema. In ogni componente della casella di controllo, non inserire & Quot; Id & Quot; in esso, che influenzerà l'associazione del modello MVC.

Il seguente codice funzionerà per l'associazione del modello:

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

I seguenti codici non sono vincolanti per il modello (la differenza qui è assegnata all'ID per ogni casella di controllo)

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

questo è quello che ho fatto per perdere i doppi valori quando ho usato Html.CheckBox (...

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

con 4 caselle selezionate, deselezionate, deselezionate, controllate che gira vero, falso, falso, falso, vero, falso in vero, falso, falso, vero. proprio quello di cui avevo bisogno

Che ne dici di qualcosa del genere?

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

Quando uso la casella di controllo HtmlHelper, preferisco di gran lunga lavorare con i dati del modulo della casella di controllo postati come un array. Non so davvero perché, so che gli altri metodi funzionano, ma penso che preferisco semplicemente trattare le stringhe separate da virgola come un array il più possibile.

Quindi fare un test 'controllato' o vero sarebbe:

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

Fare un controllo falso sarebbe:

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

La differenza principale consiste nell'utilizzare GetValues in quanto restituisce un array.

Fallo su $(document).ready:

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

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

    }
});

La mia soluzione è:

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

Più puoi trovare qui: http://www.blog.mieten.pl/2010/12/asp-net-mvc-custom-checkbox-as-solution-of-string-was-not-recognized- as-a-valid-booleano /

Ho avuto quasi lo stesso problema ma il valore di ritorno del mio controller è stato bloccato con altri valori.

Trovato una soluzione semplice ma sembra un po 'approssimativa.

Prova a digitare Viewbag. nel tuo controller e ora gli dai un nome come Viewbag.Checkbool

Ora passa alla vista e prova questo @Viewbag.Checkbool con questo otterrai il valore dal controller.

I parametri del mio controller sono così:

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

e la mia casella di controllo si aggiornerà in questo modo:

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

Usando @mmacaulay, ho pensato a questo per bool:

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

Se selezionato active = true

Se deselezionato active = false

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top