Я только что заметил, что Html.CheckBox("foo")
генерирует 2 входа вместо одного, кто-нибудь знает, почему это так?
<input id="foo" name="foo" type="checkbox" value="true" />
<input name="foo" type="hidden" value="false" />
Я только что заметил, что Html.CheckBox("foo")
генерирует 2 входа вместо одного, кто-нибудь знает, почему это так?
<input id="foo" name="foo" type="checkbox" value="true" />
<input name="foo" type="hidden" value="false" />
Ответы:
Если флажок не установлен, поле формы не отправляется. Вот почему всегда есть ложное значение в скрытом поле. Если вы оставите флажок не установленным, форма все равно будет иметь значение из скрытого поля. Именно так ASP.NET MVC обрабатывает значения флажков.
Если вы хотите это подтвердить, поставьте флажок в форме не с Html.Hidden, а с <input type="checkbox" name="MyTestCheckboxValue"></input>
. Оставьте флажок снятым, отправьте форму и посмотрите значения отправленных запросов на стороне сервера. Вы увидите, что значение флажка отсутствует. Если у вас есть скрытое поле, оно будет содержать MyTestCheckboxValue
запись со false
значением.
IsActive
, которое инициируется true
в конструкторе. Пользователь снимает флажок, но поскольку значение не отправляется на сервер, связыватель модели не получает его, и значение свойства не изменяется. Связыватель модели не должен предполагать, что если значение не отправлено, для него установлено значение false, поскольку это может быть вашим решением не отправлять это значение.
false
значение, даже если они проверены, и это сбивает с толку. Отключенные флажки вообще не должны отправлять какие-либо значения, если ASP.NET хочет быть совместимым с поведением HTTP по умолчанию.
Вы можете написать помощник для предотвращения добавления скрытого ввода:
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);
}
}
используй это:
@Html.CheckBoxSimple("foo", new {value = bar.Id})
@using Your.Name.Space
в начало вашего файла просмотра .cshtml бритвы.
System.Web.Mvc.Html
чтобы оно было доступно для всех представлений
когда флажок установлен и отправлен, выполните это
if ($('[name="foo"]:checked').length > 0)
$('[name="foo"]:hidden').val(true);
Ручной подход заключается в следующем:
bool IsDefault = (Request.Form["IsDefault"] != "false");
Это строго типизированная версия решения Александра Трофимова:
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);
}
}
Скрытый ввод вызывал проблемы со стилизованными флажками. Поэтому я создал Html Helper Extension для размещения скрытого ввода вне div, содержащего 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());
}
результат
<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">
Вы можете попробовать инициализировать конструктор вашей Модели следующим образом:
public MemberFormModel() {
foo = true;
}
и по вашему мнению:
@html.Checkbox(...)
@html.Hidden(...)
Я обнаружил, что это действительно вызывало проблемы, когда у меня была WebGrid. Сортировка ссылок в WebGrid превратится на удвоенную строку запроса или x = true & x = false в x = true, false и вызовет ошибку разбора в флажке для.
В итоге я использовал jQuery для удаления скрытых полей на стороне клиента:
<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>