Acabo de notar que Html.CheckBox("foo")genera 2 entradas en lugar de una, ¿alguien sabe por qué es así?
<input id="foo" name="foo" type="checkbox" value="true" />
<input name="foo" type="hidden" value="false" />
Acabo de notar que Html.CheckBox("foo")genera 2 entradas en lugar de una, ¿alguien sabe por qué es así?
<input id="foo" name="foo" type="checkbox" value="true" />
<input name="foo" type="hidden" value="false" />
Respuestas:
Si la casilla de verificación no está seleccionada, el campo del formulario no se envía. Es por eso que siempre hay un valor falso en el campo oculto. Si deja la casilla de verificación sin marcar, el formulario seguirá teniendo valor del campo oculto. Así es como ASP.NET MVC maneja los valores de las casillas de verificación.
Si desea confirmar eso, coloque una casilla de verificación en el formulario no con Html.Hidden, sino con <input type="checkbox" name="MyTestCheckboxValue"></input>. Deje la casilla sin marcar, envíe el formulario y observe los valores de solicitud publicados en el lado del servidor. Verá que no hay un valor de casilla de verificación. Si tuviera un campo oculto, contendría una MyTestCheckboxValueentrada con falsevalor.
IsActive, que se inicia trueen constructor. El usuario deselecciona la casilla de verificación, pero dado que el valor no se envía al servidor, el cuaderno de modelo no lo recoge y el valor de la propiedad no cambia. El cuaderno de modelo no debe suponer que si el valor no se envía, se estableció en falso, ya que podría ser su decisión no enviar este valor.
falsevalor incluso si están marcadas, y eso es confuso. Las casillas de verificación deshabilitadas no deberían enviar ningún valor, si ASP.NET quiere ser compatible con el comportamiento HTTP predeterminado.
Puede escribir un ayudante para evitar agregar la entrada oculta:
using System.Web.Mvc;
using System.Web.Mvc.Html;
public static class HelperUI
{
public static MvcHtmlString CheckBoxSimple(this HtmlHelper htmlHelper, string name, object htmlAttributes)
{
string checkBoxWithHidden = htmlHelper.CheckBox(name, htmlAttributes).ToHtmlString().Trim();
string pureCheckBox = checkBoxWithHidden.Substring(0, checkBoxWithHidden.IndexOf("<input", 1));
return new MvcHtmlString(pureCheckBox);
}
}
úsalo:
@Html.CheckBoxSimple("foo", new {value = bar.Id})
@using Your.Name.Spaceen la parte superior de su archivo de vista de afeitadora .cshtml.
System.Web.Mvc.Htmlde nombres para que sea accesible en todas las vistas
El enfoque manual es este:
bool IsDefault = (Request.Form["IsDefault"] != "false");
Esta es la versión fuertemente tipada de la solución de Alexander Trofimov:
using System.Web.Mvc;
using System.Web.Mvc.Html;
public static class HelperUI
{
public static MvcHtmlString CheckBoxSimpleFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool>> expression, object htmlAttributes)
{
string checkBoxWithHidden = htmlHelper.CheckBoxFor(expression, htmlAttributes).ToHtmlString().Trim();
string pureCheckBox = checkBoxWithHidden.Substring(0, checkBoxWithHidden.IndexOf("<input", 1));
return new MvcHtmlString(pureCheckBox);
}
}
La entrada oculta estaba causando problemas con las casillas de estilo. Así que creé una extensión de ayuda HTML para colocar la entrada oculta fuera del div que contiene CheckBox.
using System;
using System.Linq.Expressions;
using System.Text;
using System.Web.Mvc;
using System.Web.Routing;
namespace YourNameSpace
{
public static class HtmlHelperExtensions
{
public static MvcHtmlString CustomCheckBoxFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression, string labelText)
{
//get the data from the model binding
var fieldName = ExpressionHelper.GetExpressionText(expression);
var fullBindingName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(fieldName);
var fieldId = TagBuilder.CreateSanitizedId(fullBindingName);
var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
var modelValue = metaData.Model;
//create the checkbox
TagBuilder checkbox = new TagBuilder("input");
checkbox.MergeAttribute("type", "checkbox");
checkbox.MergeAttribute("value", "true"); //the visible checkbox must always have true
checkbox.MergeAttribute("name", fullBindingName);
checkbox.MergeAttribute("id", fieldId);
//is the checkbox checked
bool isChecked = false;
if (modelValue != null)
{
bool.TryParse(modelValue.ToString(), out isChecked);
}
if (isChecked)
{
checkbox.MergeAttribute("checked", "checked");
}
//add the validation
checkbox.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(fieldId, metaData));
//create the outer div
var outerDiv = new TagBuilder("div");
outerDiv.AddCssClass("checkbox-container");
//create the label in the outer div
var label = new TagBuilder("label");
label.MergeAttribute("for", fieldId);
label.AddCssClass("checkbox");
//render the control
StringBuilder sb = new StringBuilder();
sb.AppendLine(outerDiv.ToString(TagRenderMode.StartTag));
sb.AppendLine(checkbox.ToString(TagRenderMode.SelfClosing));
sb.AppendLine(label.ToString(TagRenderMode.StartTag));
sb.AppendLine(labelText); //the label
sb.AppendLine("<svg width=\"10\" height=\"10\" class=\"icon-check\"><use xlink:href=\"/icons.svg#check\"></use></svg>"); //optional icon
sb.AppendLine(label.ToString(TagRenderMode.EndTag));
sb.AppendLine(outerDiv.ToString(TagRenderMode.EndTag));
//create the extra hidden input needed by MVC outside the div
TagBuilder hiddenCheckbox = new TagBuilder("input");
hiddenCheckbox.MergeAttribute("type", HtmlHelper.GetInputTypeString(InputType.Hidden));
hiddenCheckbox.MergeAttribute("name", fullBindingName);
hiddenCheckbox.MergeAttribute("value", "false");
sb.Append(hiddenCheckbox.ToString(TagRenderMode.SelfClosing));
//return the custom checkbox
return MvcHtmlString.Create(sb.ToString());
}
Resultado
<div class="checkbox-container">
<input checked="checked" id="Model_myCheckBox" name="Model.myCheckBox" type="checkbox" value="true">
<label class="checkbox" for="Model_myCheckBox">
The checkbox label
<svg width="10" height="10" class="icon-check"><use xlink:href="/icons.svg#check"></use></svg>
</label>
</div>
<input name="Model.myCheckBox" type="hidden" value="false">
¡Esto no es un error! Agrega la posibilidad de tener siempre un valor, después de publicar el formulario en el servidor. Si desea lidiar con los campos de entrada de la casilla de verificación con jQuery, use el método prop (pase la propiedad 'marcada' como parámetro). Ejemplo:$('#id').prop('checked')
Puede intentar inicializar el constructor de su modelo así:
public MemberFormModel() {
foo = true;
}
y en tu opinión:
@html.Checkbox(...)
@html.Hidden(...)
Descubrí que esto realmente causaba problemas cuando tenía un WebGrid. Los enlaces de clasificación en WebGrid pasarían por la cadena de consulta duplicada o x = true & x = false en x = true, false y causarían un error de análisis en la casilla de verificación.
Terminé usando jQuery para eliminar los campos ocultos en el lado del cliente:
<script type="text/javascript">
$(function () {
// delete extra hidden fields created by checkboxes as the grid links mess this up by doubling the querystring parameters
$("input[type='hidden'][name='x']").remove();
});
</script>