Ответ 1
Я получил его для работы с
@Html.EditorFor(model => model.Foo)
а затем создав Boolean.cshtml в моей папке EditorTemplates и придерживаясь
@model bool?
@Html.CheckBox("", Model.GetValueOrDefault())
внутри.
Моя модель имеет логическое значение, которое должно быть равно NULL
public bool? Foo
{
get;
set;
}
поэтому в моем Razor cshtml у меня есть
@Html.CheckBoxFor(m => m.Foo)
за исключением того, что не работает. Также не бросает его (bool). Если я делаю
@Html.CheckBoxFor(m => m.Foo.Value)
который не создает ошибку, но не привязывается к моей модели при публикации, а foo имеет значение null. Каков наилучший способ отображения Foo на странице и привязать его к моей модели в сообщении?
Я получил его для работы с
@Html.EditorFor(model => model.Foo)
а затем создав Boolean.cshtml в моей папке EditorTemplates и придерживаясь
@model bool?
@Html.CheckBox("", Model.GetValueOrDefault())
внутри.
Найден ответ в подобном вопросе - Рендеринг Nullable Bool как 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>
Моя модель имеет логическое значение, которое должно быть равно NULL
Почему? Это не имеет смысла. Флажок имеет два состояния: отмечен/не установлен, или True/False, если хотите. Третьего государства нет.
Или подождите, пока вы используете модели своего домена в своих представлениях вместо просмотра моделей? Это ваша проблема. Поэтому решение для меня - использовать модель представления, в которой вы определяете простое логическое свойство:
public class MyViewModel
{
public bool Foo { get; set; }
}
и теперь у вас будет действие вашего контроллера, чтобы передать эту модель представления в представление и создать соответствующий флажок.
Упрощение примитива со скрытыми полями, чтобы выяснить, не рекомендуется ли False или Null.
Флажок не то, что вы должны использовать - на нем действительно только одно состояние: Проверено. В противном случае это может быть что угодно.
Когда поле базы данных является нулевым логическим (bool?
), UX должен использовать 3-радио кнопки, где первая кнопка представляет ваш "Проверено", вторая кнопка представляет "Не проверено", а третья кнопка представляет ваш 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, чтобы ваши переключатели переключались горизонтально (дисплей: inline- блок), вертикальный или в виде таблицы (дисплей: встроенный блок, ширина: 100 пикселей;)
В модели (я использую строку, строку для определения словаря в качестве педагогического примера. Вы можете использовать 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());
}
}
Флажок содержит только 2 значения (true, false). Nullable boolean имеет 3 значения (true, false, null), поэтому это невозможно сделать с помощью флажка.
Хорошим вариантом является использование выпадающего списка.
Model
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)
Для меня решение заключалось в изменении модели представления. Подумайте, что вы ищете счета-фактуры. Эти счета-фактуры могут быть оплачены или нет. Таким образом, ваш поиск имеет три варианта: "Платный", "Неоплаченный" или "Я не забочусь".
У меня это было первоначально как bool? поле:
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)
Конечно, я их обернул в ярлыки и указал текст, я просто имею в виду здесь другой вариант для рассмотрения.
Я бы создал шаблон для него и использовал этот шаблон с помощью EditorFor().
Вот как я это сделал:
Создайте свой шаблон, который в основном является частичным представлением, созданным мной в каталоге EditorTemplates, в разделе "Общие" в разделе "Представления" это как (например): 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()
; при условии, что вы передадите свою модель представления в выражении лямбда.
Самый чистый подход, который я мог бы предложить, - расширить расширения, доступные для 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-блоке и установите атрибут name= "Foo". Это должно быть правильно опубликовано.
<input type="checkbox" name="Foo" checked="@model.Foo.Value" /> Foo Checkbox<br />
Просто проверьте нулевое значение и верните ему 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 для модели, содержащей nullable 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 Razor
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);
}
ты можешь попробовать вот так
@Html.TextBoxFor(m => m.foo, new { type = "checkbox" })
Радиокнопки полезны, но они не позволяют отменить выбор. Если вы хотите такое поведение, тогда рассмотрите возможность использования раскрывающегося списка/выбора. Следующий код сгенерирует SelectList
, и он успешно привязывается к логическому значению, допускающему значение NULL:
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)
Это старый вопрос, и существующие ответы описывают большинство альтернатив. Но есть ли один простой вариант, если у вас есть bool? в вашей модели просмотра, и вы не заботитесь об нуле в пользовательском интерфейсе:
@Html.CheckBoxFor(m => m.boolValue ?? false);