Флажок для nullable boolean
моя модель имеет логическое значение, которое должно быть nullable
public bool? Foo
{
get;
set;
}
Так что в моей бритве cshtml у меня есть
@Html.CheckBoxFor(m => m.Foo)
за исключением того, что не работает. Так же как и кастинг с (bool). Если я это сделаю
@Html.CheckBoxFor(m => m.Foo.Value)
это не создает ошибку, но она не привязывается к моей модели при публикации, а foo имеет значение null. Какой лучший способ отобразить Foo на странице и привязать его к моей модели на посту?
17 ответов:
Я получил его на работу с
@Html.EditorFor(model => model.Foo)
и затем делает логическое значение.cshtml в моей папке EditorTemplates и прилипание
@model bool? @Html.CheckBox("", Model.GetValueOrDefault())
внутри.
нашел ответ на аналогичный вопрос -Rendering Nullable Bool as CheckBox. Это очень просто и просто работает:
@Html.CheckBox("RFP.DatesFlexible", Model.RFP.DatesFlexible ?? false) @Html.Label("RFP.DatesFlexible", "My Dates are Flexible")
это похоже на принятый ответ от @afinkelstein, за исключением того, что нам не нужен специальный "шаблон редактора"
у меня есть
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>
моя модель имеет логическое значение, которое должно быть nullable
почему? Это не имеет смысла. Флажок имеет два состояния: checked/unchecked или True/False, если хотите. Третьего государства не существует.
или подождите, вы используете свои модели домена в своих представлениях вместо моделей представления? Это твоя проблема. Поэтому решение для меня-использовать модель представления, в которой вы определите простое логическое свойство:
public class MyViewModel { public bool Foo { get; set; } }
и теперь у вас будет свой действие контроллера передайте эту модель представления в представление и сгенерируйте соответствующий флажок.
усложнение примитива со скрытыми полями, чтобы уточнить, является ли False или Null не рекомендуется.
флажок не то, что вы должны использовать-он действительно имеет только одно состояние: проверил. В противном случае, это может быть что угодно.
когда поле базы данных является логическим значением с нулевым значением (
bool?
), UX должен использовать 3-переключатели, где первая кнопка представляет ваш "проверено", вторая кнопка представляет "не проверено" и третья кнопка представляет ваш значение 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, чтобы сделать ваши переключатели горизонтальными (дисплей: встроенный блок), вертикальными или в a таблица моды (дисплей: встроенный блок; ширина: 100px;)в модели (я использую строку, строку для определения словаря в качестве педагогического примера. Вы можете использовать bool?, строка)
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()); } }
для меня решение состояло в том, чтобы изменить модель представления. Считайте, что вы ищете счета-фактуры. Эти счета могут быть оплачены или нет. Таким образом, ваш поиск имеет три варианта: платный, неоплачиваемый или "мне все равно".
у меня Это изначально было установлено как bool? поле:
public bool? PaidInvoices { get; set; }
Это заставило меня наткнуться на этот вопрос. Я в конечном итоге создал тип перечисления, и я обработал это следующим образом:
@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 значения (true, false). Nullable boolean имеет 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)
самый чистый подход, который я мог бы придумать, - это расширить доступные расширения
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>>>
но я не думаю, что это возможно.
У меня была подобная проблема в прошлом.
создать флажок ввода в HTML, и установить имя атрибута="Foo" это должно по-прежнему размещать правильно.
<input type="checkbox" name="Foo" checked="@model.Foo.Value" /> Foo Checkbox<br />
Я бы на самом деле создать шаблон для него и использовать этот шаблон с 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.В(Х => Х.MyNullableBooleanCheckboxToBe, "CheckboxTemplate")
вот и все.
Шаблоны настолько сильны в MVC, используйте их.. Вы можете создать целую страницу в качестве шаблона, который вы будете использовать с
@Html.EditorFor()
; при условии, что вы передаете свои модели представления в лямбда-выражении..
просто проверьте значение 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 для модели, которая содержит нулевой bool...
разделить nullable 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.
все ответы выше пришли с его собственными проблемами. Самый простой / чистый способ ИМО-создать помощника
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)
в моем сценарии флажок nullable означает, что сотрудник еще не задал вопрос клиенту, поэтому он завернут в
.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); }