Mir ist gerade aufgefallen, dass Html.CheckBox("foo")2 Eingänge anstelle von einem generiert werden. Weiß jemand, warum das so ist?
<input id="foo" name="foo" type="checkbox" value="true" />
<input name="foo" type="hidden" value="false" />
Mir ist gerade aufgefallen, dass Html.CheckBox("foo")2 Eingänge anstelle von einem generiert werden. Weiß jemand, warum das so ist?
<input id="foo" name="foo" type="checkbox" value="true" />
<input name="foo" type="hidden" value="false" />
Antworten:
Wenn das Kontrollkästchen nicht aktiviert ist, wird das Formularfeld nicht gesendet. Deshalb gibt es im versteckten Feld immer einen falschen Wert. Wenn Sie das Kontrollkästchen nicht aktivieren, hat das Formular weiterhin einen Wert aus dem ausgeblendeten Feld. Auf diese Weise verarbeitet ASP.NET MVC Kontrollkästchenwerte.
Wenn Sie dies bestätigen möchten, aktivieren Sie das Kontrollkästchen nicht mit Html.Hidden, sondern mit <input type="checkbox" name="MyTestCheckboxValue"></input>. Lassen Sie das Kontrollkästchen deaktiviert, senden Sie das Formular und sehen Sie sich die auf der Serverseite veröffentlichten Anforderungswerte an. Sie werden sehen, dass es keinen Kontrollkästchenwert gibt. Wenn Sie ein verstecktes Feld hätten, würde es einen MyTestCheckboxValueEintrag mit falseWert enthalten.
IsActive, die trueim Konstruktor initiiert wird . Das Kontrollkästchen des Benutzers wird deaktiviert. Da der Wert jedoch nicht an den Server gesendet wird, wird er vom Modellordner nicht übernommen und der Eigenschaftswert wird nicht geändert. Der Modellordner sollte nicht davon ausgehen, dass der Wert, wenn er nicht gesendet wird, auf false gesetzt wurde, da Sie möglicherweise entscheiden, diesen Wert nicht zu senden.
falseWerte, auch wenn sie aktiviert sind, und das ist verwirrend. Deaktivierte Kontrollkästchen sollten überhaupt keinen Wert senden, wenn ASP.NET mit dem Standard-HTTP-Verhalten kompatibel sein soll.
Sie können einen Helfer schreiben, um das Hinzufügen der versteckten Eingabe zu verhindern:
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);
}
}
benutze es:
@Html.CheckBoxSimple("foo", new {value = bar.Id})
@using Your.Name.Spaceoben in Ihrer .cshtml-Rasiermesser-Ansichtsdatei hinzuzufügen .
System.Web.Mvc.Html, um in allen Ansichten zugänglich zu sein
Der manuelle Ansatz ist folgender:
bool IsDefault = (Request.Form["IsDefault"] != "false");
Dies ist die stark typisierte Version von Alexander Trofimovs Lösung:
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);
}
}
Die versteckte Eingabe verursachte Probleme mit gestalteten Kontrollkästchen. Also habe ich eine HTML-Hilfserweiterung erstellt, um die versteckte Eingabe außerhalb des Divs mit der CheckBox zu platzieren.
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());
}
Ergebnis
<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">
Dies ist kein Fehler! Es wird die Möglichkeit hinzugefügt, nach dem Posten des Formulars auf dem Server immer einen Wert zu haben. Wenn Sie mit jQuery Eingabefelder für Kontrollkästchen bearbeiten möchten, verwenden Sie die Methode prop (übergeben Sie die Eigenschaft 'checked' als Parameter). Beispiel:$('#id').prop('checked')
Sie können versuchen, den Konstruktor Ihres Modells folgendermaßen zu initialisieren:
public MemberFormModel() {
foo = true;
}
und aus Ihrer Sicht:
@html.Checkbox(...)
@html.Hidden(...)
Ich fand, dass dies wirklich Probleme verursachte, als ich ein WebGrid hatte. Die Sortierlinks im WebGrid werden durch den verdoppelten Querystring oder x = true & x = false in x = true, false umgewandelt und verursachen einen Analysefehler im Kontrollkästchen für.
Am Ende habe ich jQuery verwendet, um die versteckten Felder auf der Clientseite zu löschen:
<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>