I just noticed that Html.CheckBox(\"foo\")
generates 2 inputs instead of one, anybody knows why is this so ?
The hidden input was causing problems with styled checkboxes. So I created a Html Helper Extension to place the hidden input outside the div containing the 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(this HtmlHelper htmlHelper, Expression> 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(""); //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());
}
Result