Questo funziona abbastanza bene con un modello personalizzato legante e regolare HTML ...
In primo luogo, il modulo HTML in Razor sintassi:
@using (Html.BeginForm("Action", "Controller", FormMethod.Post)) {
<ol>
<li><input type="textbox" name="tBox" value="example of another form element" /></li>
<li><input type="checkbox" name="cBox" value="1" /> One</li>
<li><input type="checkbox" name="cBox" value="2" /> Two</li>
<li><input type="checkbox" name="cBox" value="3" /> Three</li>
<li><input type="checkbox" name="cBox" value="4" /> Four</li>
<li><input type="checkbox" name="cBox" value="5" /> Five</li>
<li><input type="submit" /></li>
</ol>
}
(FormMethod.Post
potrebbe anche essere .Get
, non importa per questo)
Poi, nel senso proprio MVC avere un oggetto del modello che rappresenta il modulo di invio:
public class CheckboxListExampleModel {
public string TextboxValue { get; set; }
public List<int> CheckboxValues { get; set; }
}
E una classe di raccoglitore modello personalizzata (mi piace inserire questo modello all'interno del modello, quindi ripeterò il modello creato sopra per mostrare dove lo aggiungerei.Riposte in inoltre permette il legante da usare setter di proprietà privata, che è una buona cosa):
public class CheckboxListExampleModel {
public string TextboxValue { get; private set; }
public List<int> CheckboxValues { get; private set; }
public class Binder : DefaultModelBinder {
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
var model = new CheckboxListExampleModel();
model.TextboxValue = bindingContext.GetValueAsString("tBox");
string checkboxCsv = bindingContext.GetValueAsString("cBox");
// checkboxCsv will be a comma-separated list of the 'value' attributes
// of all the checkboxes with name "cBox" which were checked
model.CheckboxValues = checkboxCsv.SplitCsv<int>();
return model;
}
}
}
.GetValueAsString()
è un metodo di estensione utilizzato per chiarezza, qui è:
public static string GetValueAsString(this ModelBindingContext context, string formValueName, bool treatWhitespaceAsNull = true) {
var providerResult = context.ValueProvider.GetValue(formValueName);
if (providerResult.IsNotNull() && !providerResult.AttemptedValue.IsNull()) {
if (treatWhitespaceAsNull && providerResult.AttemptedValue.IsNullOrWhiteSpace()) {
return null;
} else {
return providerResult.AttemptedValue.Trim();
}
}
return null;
}
.SplitCsv<T>()
è anche un metodo di estensione, ma è un codice abbastanza comune e abbastanza confidenziale da lasciarlo come esercizio per il lettore.
E, infine, la vostra azione per gestire il modulo di conferma:
[HttpPost]
public ActionResult Action([ModelBinder(typeof(CheckboxListExampleModel.Binder))] CheckboxListExampleModel model) {
// stuff
}
idea non è male, ma non funziona quando si utilizza un modulo con altri elementi di questo. Per esempio, c'è un nome utente/password + una raccolta di checkbox, in questo modo non può funzionare:/ – Erick
@Erick, naturalmente che può funzionare. Il tuo modello di vista ora conterrà proprietà semplici come 'Username' e' Password' e una collezione 'IEnumerable' che conterrà le informazioni sulle caselle di controllo. Ora invece di usare 'Html.EditorForModel' nel tuo form avresti semplice' <% = Html.TextBoxFor (x => x.Username)%> 'e' <% = Html.PasswordFor (x => x.Password) %> 'e a' <% = Html.EditorFor (x => x.MyCheckboxes)%> 'che renderizza lo stesso modello di editor. –
Ho letto molti modi per realizzare questo, e questa era di gran lunga la soluzione più elegante. Grazie! – JimDaniel