checkbox为可空布尔值

我的模型有一个必须为空的布尔值

public bool? Foo { get; set; } 

所以在我的剃刀cshtml我有

 @Html.CheckBoxFor(m => m.Foo) 

除了不起作用。 (bool)也没有。 如果我做

 @Html.CheckBoxFor(m => m.Foo.Value) 

这并不会产生错误,但是在发布和foo被设置为null时,它不会绑定到我的模型。 什么是在页面上显示Foo的最佳方式,并使其绑定到我的模型在一个职位?

我得到了它的工作

 @Html.EditorFor(model => model.Foo) 

然后在我的EditorTemplates文件夹中创build一个Boolean.cshtml并粘贴

 @model bool? @Html.CheckBox("", Model.GetValueOrDefault()) 

内。

我有bool? IsDisabled { get; set; } bool? IsDisabled { get; set; } bool? IsDisabled { get; set; }模型中。 如果在视图中插入。

 <div class="inputClass" id="disabled"> <div> @if(Model.IsDisabled==null) { Model.IsDisabled = false; } @Html.CheckBoxFor(model => model.IsDisabled.Value) </div> </div> 

find类似的问题的答案 – 渲染Nullable Bool作为checkbox 。 这是非常简单的,只是工作:

 @Html.CheckBox("RFP.DatesFlexible", Model.RFP.DatesFlexible ?? false) @Html.Label("RFP.DatesFlexible", "My Dates are Flexible") 

这就像@afinkelstein接受的答案,除了我们不需要特殊的“编辑器模板”

我的模型有一个必须为空的布尔值

为什么? 这没有意义。 一个checkbox有两个状态:checked / unchecked,或者True / False。 没有第三个国家。

或者等待您在视图中使用域模型而不是视图模型? 这是你的问题。 所以我的解决scheme是使用一个视图模型,你将在其中定义一个简单的布尔属性:

 public class MyViewModel { public bool Foo { get; set; } } 

现在你将有你的控制器动作传递这个视图模型到视图并生成适当的checkbox。

使用隐藏字段复杂化一个原语来澄清是否不推荐使用False或Null。

checkbox不是你应该使用的 – 它只有一个状态: 检查 。 否则,它可能是任何东西。

当你的数据库字段是一个可空布尔( bool? )时,UX应该使用三个单选button,其中第一个button代表“Checked”,第二个button代表“Not Checked”,第三个button代表null,无论null表示的语义。 您可以使用<select><option>下拉列表来保存房地产,但是用户必须点击两次,select也不会立即清晰。

  1 0 null True False Not Set Yes No Undecided Male Female Unknown On Off Not Detected 

定义为名为RadioButtonForSelectList的扩展RadioButtonList为你创build单选button,包括选定的/选中的值,并设置<div class="RBxxxx">这样你就可以使用css让你的单选button变成水平的(display:内联块),垂直或表格方式(显示:内联块;宽度:100px;)

在模型中(我使用string,字典定义的string作为教学的例子,你可以使用bool ?,string)

 public IEnumerable<SelectListItem> Sexsli { get; set; } SexDict = new Dictionary<string, string>() { { "M", "Male"}, { "F", "Female" }, { "U", "Undecided" }, }; //Convert the Dictionary Type into a SelectListItem Type Sexsli = SexDict.Select(k => new SelectListItem { Selected = (k.Key == "U"), Text = k.Value, Value = k.Key.ToString() }); <fieldset id="Gender"> <legend id="GenderLegend" title="Gender - Sex">I am a</legend> @Html.RadioButtonForSelectList(m => m.Sexsli, Model.Sexsli, "Sex") @Html.ValidationMessageFor(m => m.Sexsli) </fieldset> public static class HtmlExtensions { public static MvcHtmlString RadioButtonForSelectList<TModel, TProperty>( this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> listOfValues, String rbClassName = "Horizontal") { var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); var sb = new StringBuilder(); if (listOfValues != null) { // Create a radio button for each item in the list foreach (SelectListItem item in listOfValues) { // Generate an id to be given to the radio button field var id = string.Format("{0}_{1}", metaData.PropertyName, item.Value); // Create and populate a radio button using the existing html helpers var label = htmlHelper.Label(id, HttpUtility.HtmlEncode(item.Text)); var radio = String.Empty; if (item.Selected == true) { radio = htmlHelper.RadioButtonFor(expression, item.Value, new { id = id, @checked = "checked" }).ToHtmlString(); } else { radio = htmlHelper.RadioButtonFor(expression, item.Value, new { id = id }).ToHtmlString(); }// Create the html string to return to client browser // eg <input data-val="true" data-val-required="You must select an option" id="RB_1" name="RB" type="radio" value="1" /><label for="RB_1">Choice 1</label> sb.AppendFormat("<div class=\"RB{2}\">{0}{1}</div>", radio, label, rbClassName); } } return MvcHtmlString.Create(sb.ToString()); } } 

对我来说,解决scheme是改变视图模型。 考虑你正在寻找发票。 这些发票可以支付或不支付。 所以你的search有三个选项:付费,无偿或“我不在乎”。

我有这个最初设置为布尔? 领域:

 public bool? PaidInvoices { get; set; } 

这使我绊倒了这个问题。 我结束了创build一个枚举types,我处理这个如下:

 @Html.RadioButtonFor(m => m.PaidInvoices, PaidStatus.NotSpecified, new { @checked = true }) @Html.RadioButtonFor(m => m.PaidInvoices, PaidStatus.Yes) @Html.RadioButtonFor(m => m.PaidInvoices, PaidStatus.No) 

当然,我有他们包装在标签,并具有指定的文字,我的意思是这里有另一个select考虑。

checkbox只能提供2个值(true,false)。 可空布尔值有3个值(true,false,null),所以不可能用checkbox来实现。

一个不错的select是使用下拉菜单。

模型

 public bool? myValue; public List<SelectListItem> valueList; 

调节器

 model.valueList = new List<SelectListItem>(); model.valueList.Add(new SelectListItem() { Text = "", Value = "" }); model.valueList.Add(new SelectListItem() { Text = "Yes", Value = "true" }); model.valueList.Add(new SelectListItem() { Text = "No", Value = "false" }); 

视图

 @Html.DropDownListFor(m => m.myValue, valueList) 

我可以想到的最简洁的方法是扩展可用于HtmlHelper的扩展,同时仍然重用框架提供的function。

 public static MvcHtmlString CheckBoxFor<T>(this HtmlHelper<T> htmlHelper, Expression<Func<T, bool?>> expression, IDictionary<string, object> htmlAttributes) { ModelMetadata modelMeta = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); bool? value = (modelMeta.Model as bool?); string name = ExpressionHelper.GetExpressionText(expression); return htmlHelper.CheckBox(name, value ?? false, htmlAttributes); } 

我尝试了“整形”expression式,以允许直接传递给本机CheckBoxFor<Expression<Func<T, bool>>>但是我不认为这是可能的。

我过去也有类似的问题。

在HTML中创build一个checkboxinput,并设置属性名称=“Foo”这应该仍然正确发布。

 <input type="checkbox" name="Foo" checked="@model.Foo.Value" /> Foo Checkbox<br /> 

我实际上会为它创build一个模板,并用EditorFor()来使用该模板。

我是这样做的:

  1. 创build我的模板,这基本上是我在EditorTemplates目录下创build的部分视图,在Shared下的Views下命名为(例如): CheckboxTemplate

     @using System.Globalization @using System.Web.Mvc.Html @model bool? @{ bool? myModel = false; if (Model.HasValue) { myModel = Model.Value; } } <input type="checkbox" checked="@(myModel)" name="@ViewData.TemplateInfo.HtmlFieldPrefix" value="True" style="width:20px;" /> 
  2. 像这样使用它(在任何视图中):

    @ Html.EditorFor(x => x.MyNullableBooleanCheckboxToBe,“CheckboxTemplate”)

就这样。

模板在MVC中非常强大,可以使用它们。你可以创build一个完整的页面作为模板,你可以使用@Html.EditorFor() ; 只要你在lambdaexpression式中传递它的视图模型。

只要检查空值,并返回false:

 @{ bool nullableValue = ((Model.nullableValue == null) || (Model.nullableValue == false)) ? false : true; } @Html.CheckBoxFor(model => nullableValue) 

我也面临同样的问题。 我尝试了以下方法来解决问题,因为我不想更改数据库并再次生成EDMX。

 @{ bool testVar = (Model.MYVar ? true : false); } <label>@Html.CheckBoxFor(m => testVar)testVar</label><br /> 

当为包含可为空的模型的模型创buildEditorTemplate …

  • 将可空bool分解为2个布尔值:

     // Foo is still a nullable boolean. public bool? Foo { get { if (FooIsNull) return null; return FooCheckbox; } set { FooIsNull = (value == null); FooCheckbox = (value ?? false); } } // These contain the value of Foo. Public only so they are visible in Razor views. public bool FooIsNull { get; set; } public bool FooCheckbox { get; set; } 
  • 在编辑器模板中:

     @Html.HiddenFor(m => m.FooIsNull) @if (Model.FooIsNull) { // Null means "checkbox is hidden" @Html.HiddenFor(m => m.FooCheckbox) } else { @Html.CheckBoxFor(m => m.FooCheckbox) } 
  • 不要回发原始属性Foo,因为现在是从FooIsNull和FooCheckbox中计算出来的。

以上所有的答案都有它自己的问题。 IMO最简单/最干净的方式就是创build一个帮手

MVC5剃刀

App_Code文件/ Helpers.cshtml

 @helper CheckBoxFor(WebViewPage page, string propertyName, bool? value, string htmlAttributes = null) { if (value == null) { <div class="checkbox-nullable"> <input type="checkbox" @page.Html.Raw(htmlAttributes)> </div> } else if (value == true) { <input type="checkbox" value="true" @page.Html.Raw(htmlAttributes) checked> } else { <input type="checkbox" value="false" @page.Html.Raw(htmlAttributes)> } } 

用法

 @Helpers.CheckBoxFor(this, "IsPaymentRecordOk", Model.IsPaymentRecordOk) 

在我的情况下,一个可以为空的checkbox意味着一个工作人员还没有向客户提问,所以它被包装在一个.checkbox-nullable以便您可以适当地devise风格,并帮助最终用户确定它既不是true也不是false

CSS

 .checkbox-nullable { border: 1px solid red; padding: 3px; display: inline-block; } 

扩展方法:

  public static MvcHtmlString CheckBoxFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool?>> expression) { return htmlHelper.CheckBoxFor<TModel>(expression, null); } public static MvcHtmlString CheckBoxFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool?>> expression, object htmlAttributes) { ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); bool? isChecked = null; if (metadata.Model != null) { bool modelChecked; if (Boolean.TryParse(metadata.Model.ToString(), out modelChecked)) { isChecked = modelChecked; } } return htmlHelper.CheckBox(ExpressionHelper.GetExpressionText(expression), isChecked??false , htmlAttributes); } 
 @{ bool testVar = ((bool)item.testVar ? true : false); } @Html.DisplayFor(modelItem => testVar) 

这是一个古老的问题,现有的答案描述了大部分的select。 但有一个简单的select,如果你有布尔? 在你的viewmodel中,你不关心你的用户界面中的null:

 @Html.CheckBoxFor(m => m.boolValue ?? false);