Esto funciona bastante bien utilizando un aglutinante de modelos personalizados y HTML normal ...
En primer lugar, su formulario HTML en Razor sintaxis:
@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
también podría ser .Get
, no importa para esto)
Luego, en el buen sentido MVC tener un objeto de modelo que representa el envío de formularios:
public class CheckboxListExampleModel {
public string TextboxValue { get; set; }
public List<int> CheckboxValues { get; set; }
}
Y una clase de encuadernador de modelo personalizado (me gusta poner esto dentro del modelo encuadernado, así que repetiré el modelo creado arriba para mostrar dónde lo agregaría.Si lo coloca en el interior también permite que el ligante a utilizar emisores de propiedad privada, que es una buena 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()
es un método de extensión utilizada para mayor claridad, aquí está:
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>()
es también un método de extensión, pero es una necesidad bastante común y un código lo suficientemente complicado como para dejarlo como un ejercicio para el lector.
Y, por último, su acción para manejar el envío de formulario:
[HttpPost]
public ActionResult Action([ModelBinder(typeof(CheckboxListExampleModel.Binder))] CheckboxListExampleModel model) {
// stuff
}
idea no es mala, pero no funciona cuando se utiliza un formulario con otros artículos que esto. Digamos, por ejemplo, que hay un nombre de usuario/contraseña + una colección de casillas, de esta manera no puede funcionar:/ – Erick
@Erick, por supuesto que puede funcionar. Su modelo de vista ahora contendrá propiedades simples como 'Nombre de usuario' y' Contraseña' y una propiedad de colección 'IEnumerable' que contendrá la información de las casillas de verificación. Ahora, en lugar de usar 'Html.EditorForModel' en tu formulario, tendrías' '% simple = Html.TextBoxFor (x => x.Username)%>' y '<% = Html.PasswordFor (x => x.Password) %> 'y a' <% = Html.EditorFor (x => x.MyCheckboxes)%> 'que mostrarán la misma plantilla de editor. –
He leído muchas formas de lograr esto, y esta fue de lejos la solución más elegante. ¡Gracias! – JimDaniel