我的模型有一个布尔值,必须为空
public bool? Foo
{
get;
set;
}
所以在我的剃刀cshtml中
@Html.CheckBoxFor(m => m.Foo)
除了那行不通。也不会使用(bool)对其进行强制转换。如果我做
@Html.CheckBoxFor(m => m.Foo.Value)
不会产生错误,但是在发布且foo设置为null时不会绑定到我的模型。在页面上显示Foo并将其绑定到帖子上的模型的最佳方法是什么?
我的模型有一个布尔值,必须为空
public bool? Foo
{
get;
set;
}
所以在我的剃刀cshtml中
@Html.CheckBoxFor(m => m.Foo)
除了那行不通。也不会使用(bool)对其进行强制转换。如果我做
@Html.CheckBoxFor(m => m.Foo.Value)
不会产生错误,但是在发布且foo设置为null时不会绑定到我的模型。在页面上显示Foo并将其绑定到帖子上的模型的最佳方法是什么?
Answers:
我知道了
@Html.EditorFor(model => model.Foo)
然后在我的EditorTemplates文件夹中制作一个Boolean.cshtml并粘贴
@model bool?
@Html.CheckBox("", Model.GetValueOrDefault())
内。
HasValue
属性创建一个复选框,而不是实际的布尔值。无论基础值是多少,都会创建一个选中的复选框。如果可为空的值,则它将始终为true。
在类似的问题(将Nullable Bool渲染为CheckBox)中找到了答案。这非常简单,并且可以正常工作:
@Html.CheckBox("RFP.DatesFlexible", Model.RFP.DatesFlexible ?? false)
@Html.Label("RFP.DatesFlexible", "My Dates are Flexible")
就像@afinkelstein接受的答案一样,只是我们不需要特殊的“编辑器模板”
我有bool? IsDisabled { get; set; }
模特。如果在View中插入。
<div class="inputClass" id="disabled">
<div>
@if(Model.IsDisabled==null)
{
Model.IsDisabled = false;
}
@Html.CheckBoxFor(model => model.IsDisabled.Value)
</div>
</div>
我的模型有一个布尔值,必须为空
为什么?这没有道理。复选框具有两种状态:选中/未选中,或者如果愿意,则为True / False。没有第三种状态。
还是等待您在视图中使用域模型而不是视图模型?那是你的问题。因此,对我来说,解决方案是使用视图模型,在其中定义一个简单的布尔属性:
public class MyViewModel
{
public bool Foo { get; set; }
}
现在您将使控制器动作将此视图模型传递给视图并生成适当的复选框。
将具有隐藏字段的原语复杂化以阐明是否建议使用False或Null。
Checkbox不是您应该使用的-实际上它只有一种状态:Checked。否则,可能是任何事情。
当您的数据库字段是可为空的布尔值时(bool?
)时,UX应使用3-Radio Buttons,其中第一个按钮代表您的“已检查”,第二个按钮代表“未检查”,第三个按钮代表您的null,无论null表示。您可以使用一个<select><option>
下拉列表来保存房地产,但是用户必须单击两次,选择的瞬间性就不那么明显了。
1 0 null
True False Not Set
Yes No Undecided
Male Female Unknown
On Off Not Detected
RadioButtonList(定义为名为RadioButtonForSelectList的扩展名)为您构建单选按钮(包括选定/选中的值)并进行设置,<div class="RBxxxx">
以便您可以使用CSS使单选按钮变为水平(显示:行内块),垂直或以表格形式显示(显示:行内块;宽度: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
// e.g. <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());
}
}
对我来说,解决方案是更改视图模型。考虑您正在搜索发票。这些发票可以支付或不支付。因此,您的搜索有三个选项:“付费”,“未付费”或“我不在乎”。
我最初把它设置为布尔值吗?领域:
public bool? PaidInvoices { get; set; }
这使我偶然发现了这个问题。我最终创建了一个Enum类型,并按如下方式进行处理:
@Html.RadioButtonFor(m => m.PaidInvoices, PaidStatus.NotSpecified, new { @checked = true })
@Html.RadioButtonFor(m => m.PaidInvoices, PaidStatus.Yes)
@Html.RadioButtonFor(m => m.PaidInvoices, PaidStatus.No)
当然,我将它们包裹在标签中并指定了文本,我只是说这是要考虑的另一种选择。
复选框仅为您提供2个值(真,假)。Nullable布尔值具有3个值(true,false,null),因此无法使用复选框来实现。
一个不错的选择是改用下拉菜单。
模型
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)
我实际上会为其创建一个模板,并将其与EditorFor()一起使用。
这是我的做法:
创建我的模板,基本上是我在EditorTemplates目录中的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;" />
这样使用它(在任何视图中):
@ Html.EditorFor(x => x.MyNullableBooleanCheckboxToBe,“ CheckboxTemplate”)
就这样。
模板在MVC中是如此强大,请使用它们。您可以将整个页面创建为模板,并与@Html.EditorFor()
; 一起使用。只要您在lambda表达式中传递其视图模型。
我能想到的最简洁的方法是扩展可用的扩展,HtmlHelper
同时仍然重用框架提供的功能。
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);
}
我尝试对表达式进行“整形”以允许直接传递给本地人,CheckBoxFor<Expression<Func<T, bool>>>
但我认为这是不可能的。
public static MvcHtmlString CheckBoxFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool?>> expression, object htmlAttributes)
使它起作用:我使用了它,效果非常好。
我过去也遇到过类似的问题。
在HTML中创建一个Checkbox输入,并设置属性名称=“ Foo”。这仍应正确发布。
<input type="checkbox" name="Foo" checked="@model.Foo.Value" /> Foo Checkbox<br />
只需检查null值并返回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 />
为包含可为空布尔的模型制作EditorTemplate时...
将可为空的布尔拆分为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创建助手的最简单/最简洁的方法
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-nullable
以便您可以适当地设置样式并帮助最终用户识别它既不是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);
}
单选按钮很有用,但不允许您取消选择。如果您想要这种行为,请考虑使用下拉菜单/选择。以下代码将生成,SelectList
并成功绑定到可为空的布尔值:
public static SelectList GetBoolTriState()
{
var items = new List<SelectListItem>
{
new SelectListItem {Value = "", Text = ""},
new SelectListItem {Value = "True", Text = "Yes"},
new SelectListItem {Value = "False", Text = "No"},
};
return new SelectList(items, "Value", "Text");
}
@{ bool testVar = ((bool)item.testVar ? true : false); }
@Html.DisplayFor(modelItem => testVar)
你可以这样尝试
@Html.TextBoxFor(m => m.foo, new { type = "checkbox" })
这是一个古老的问题,现有的答案描述了大多数替代方案。但是,如果您有布尔值,有一个简单的选择?在您的视图模型中,并且您不关心UI中的null:
@Html.CheckBoxFor(m => m.boolValue ?? false);