我的一个对象上有一个属性,它是一个可以为空的布尔值,我希望我的逻辑有真正的表示是,false是否为N而null为N / A.现在因为我将在许多不同的对象上拥有这样的多个属性,所以最有意义的是为这些属性创建编辑器和显示模板。我将使用jQuery UI来应用buttonset的可视元素,但这一切都有效,但是现在,这超出了我的问题范围。我的编辑器模板看起来像这样。
@model bool?
<div data-ui="buttonset">
@Html.RadioButtonFor(x => x, true, new { id = ViewData.TemplateInfo.GetFullHtmlFieldId("") + "Yes"}) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))Yes">Yes</label>
@Html.RadioButtonFor(x => x, false, new { id = ViewData.TemplateInfo.GetFullHtmlFieldId("") + "No" }) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))No">No</label>
@Html.RadioButtonFor(x => x, "null", new { id = ViewData.TemplateInfo.GetFullHtmlFieldId("") + "NA" }) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))NA">N/A</label>
</div>
我的问题是,在任何情况下我都无法使用此编辑器模板正确显示模型的当前值。因为我没有在此范围内呈现模型的属性而是模型本身,所以MVC3中的内置逻辑将不会正确设置checked属性,因为检查是为了验证名称不为空或为null(请参阅MVC3) source,InputExtensions.cs:第#259行)。我无法通过与模型进行比较来动态设置checked属性,因为浏览器会检查有关已检查属性是否存在值的单选按钮,因此即使我的单选按钮看起来如下所示,最后一个按钮仍然是选中的
<div class="span-4" data-ui="buttonset">
<input checked="checked" id="MyObject_BooleanValueYes" name="MyObject.BooleanValue" type="radio" value="True" /><label for="MyObject_BooleanValueYes">Yes</label>
<input checked="" id="MyObject_BooleanValueNo" name="MyObject.BooleanValue" type="radio" value="False" /><label for="MyObject_BooleanValueNo">No</label>
<input checked="" id="MyObject_BooleanValueNA" name="MyObject.BooleanValue" type="radio" value="null" /><label for="MyObject_BooleanValueNA">N/A</label>
</div><span class="field-validation-valid" data-valmsg-for="MyObject.BooleanValue" data-valmsg-replace="true"></span> </div>
我不能使用类似if?truevalue:falsevalue
之类的东西有条件地添加HtmlAttribute,因为真/假部分会有不同的匿名类型,我会收到错误。
我正在努力应该如何做到这一点,并希望你们中的一个人有关于如何解决这个问题的建议?
答案 0 :(得分:27)
@model bool?
<div data-ui="buttonset">
@{
Dictionary<string, object> yesAttrs = new Dictionary<string, object>();
Dictionary<string, object> noAttrs = new Dictionary<string, object>();
Dictionary<string, object> nullAttrs = new Dictionary<string, object>();
yesAttrs.Add("id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "Yes");
noAttrs.Add("id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "No");
nullAttrs.Add("id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "NA");
if (Model.HasValue && Model.Value)
{
yesAttrs.Add("checked", "checked");
}
else if (Model.HasValue && !Model.Value)
{
noAttrs.Add("checked", "checked");
}
else
{
nullAttrs.Add("checked", "checked");
}
}
@Html.RadioButtonFor(x => x, "true", yesAttrs) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))Yes">Yes</label>
@Html.RadioButtonFor(x => x, "false", noAttrs) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))No">No</label>
@Html.RadioButtonFor(x => x, "null", nullAttrs) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))NA">N/A</label>
</div>
答案 1 :(得分:2)
一些扩展方法如何保持“一条线来统治它们”的乐趣。 : - )
public static class DictionaryHelper
{
// This returns the dictionary so that you can "fluently" add values
public static IDictionary<TKey, TValue> AddIf<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, bool addIt, TKey key, TValue value)
{
if (addIt)
dictionary.Add(key, value);
return dictionary;
}
}
然后在您的模板文件中,您只需更改添加其他参数的签名,包括checked =“checked”属性。
@model bool?
<div data-ui="buttonset">
@Html.RadioButtonFor(x => x, true, new Dictionary<string,object>()
.AddIf(true, "id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "Yes")
.AddIf(Model.HasValue && Model.Value, "checked", "checked")
) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))Yes">Yes</label>
@Html.RadioButtonFor(x => x, false, new Dictionary<string,object>()
.AddIf(true, "id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "No")
.AddIf(Model.HasValue && !Model.Value, "checked", "checked")
) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))No">No</label>
@Html.RadioButtonFor(x => x, "null", new Dictionary<string,object>()
.AddIf(true, "id", ViewData.TemplateInfo.GetFullHtmlFieldId("") + "NA")
.AddIf(!Model.HasValue, "checked", "checked")
) <label for="@(ViewData.TemplateInfo.GetFullHtmlFieldId(""))NA">N/A</label>
</div>
答案 2 :(得分:2)
问题是你需要设置checked
属性,因为Html.RadioButtonFor
没有根据可空的bool检查单选按钮(这似乎是一个缺陷)。
另外,通过将单选按钮放在标签标签内,您可以通过单击标签来选择值。
@model bool?
<label>
<span>n/a</span>
@Html.RadioButtonFor(x => x, "", !Model.HasValue ? new { @checked=true } : null)
</label>
<label>
<span>Yes</span>
@Html.RadioButtonFor(x => x, true, Model.GetValueOrDefault() ? new { @checked = true } : null)
</label>
<label>
<span>No</span>
@Html.RadioButtonFor(x => x, false, Model.HasValue && !Model.Value ? new { @checked = true } : null)
</label>
答案 3 :(得分:1)
你只需要像这样处理特殊的null情况:
<label class="radio">
@Html.RadioButtonFor(x => x.DefaultBillable, "", new { @checked = !this.Model.DefaultBillable.HasValue })
Not set
</label>
<label class="radio">
@Html.RadioButtonFor(x => x.DefaultBillable, "false")
Non-Billable
</label>
<label class="radio">
@Html.RadioButtonFor(x => x.DefaultBillable, "true")
Billable
</label>
答案 4 :(得分:0)
您可以使用@helper简化已接受的答案:
@model bool?
<div data-ui="buttonset">
@Radio(true, "Yes", "Yes")
@Radio(false, "No", "No")
@Radio(null, "N/A", "NA")
</div>
@helper Radio(bool? buttonValue, string buttonLabel, string buttonId)
{
Dictionary<string, object> attrs = new Dictionary<string, object>();
// Unique button id
string id = ViewData.TemplateInfo.GetFullHtmlFieldId("") + buttonId;
attrs.Add("id", id);
// Check the active button
if (Model == buttonValue)
{
attrs.Add("checked", "checked");
}
@Html.RadioButtonFor(m => m, buttonValue, attrs) <label for="@id">@buttonLabel</label>
}
答案 5 :(得分:0)
使用上面的Canvas示例,我建立了一个自定义模型并进行查看,因此您可以通过模型控制值并在代码中对其进行编辑,布尔值并不总是yes / no /(n / a),因此这里是它在MVC5中的外观。
为可空布尔使用通用模型
public class Customisable_NullableRadioBool
{
public bool? Result { get; set; }
public string TrueLabel { get; set; }
public string FalseLabel { get; set; }
public string NullLabel { get; set; }
public string AttributeTitle { get; set; }
}
以下是CSHTML的存储位置: 〜/ Views / Shared / EditorTemplates / Customisable_NullableRadioBool.cshtml
@model Customisable_NullableRadioBool
@Model.AttributeTitle<br />
<div class="control-group">
<label>
@Html.RadioButtonFor(x => x.Result, "", !Model.Result.HasValue ? new { @checked = true } : null)
<span>@Model.NullLabel</span>
</label>
<br />
<label>
@Html.RadioButtonFor(x => x.Result, true, Model.Result.GetValueOrDefault() ? new { @checked = true } : null)
<span>@Model.TrueLabel</span>
</label>
<br />
<label>
@Html.RadioButtonFor(x => x.Result, false, Model.Result.HasValue && !Model.Result.Value ? new { @checked = true } : null)
<span>@Model.FalseLabel</span>
</label>
</div>
然后您可以在项目的其余部分引用泛型类和编辑器模板,并像这样呈现编辑器模板。
@Html.EditorFor(m => m.YourCustomisable_NullableBool, "Customisable_NullableRadioBool")
渲染结果示例