Карта MVC для nullable bool в модели

С моделью просмотра, содержащей поле:

public bool? IsDefault { get; set; }

Я получаю сообщение об ошибке при попытке сопоставить в представлении:

<%= Html.CheckBoxFor(model => model.IsDefault) %>

Невозможно неявно преобразовать тип 'bool?' на "bool". Явное преобразование существует (вы пропускаете листинг?)

Я пробовал кастинг и использовал .Value и не работал.

Обратите внимание, что поведение, которое я хотел бы, заключается в том, что для представления формы следует установить IsDefault в модели как true или false. Значение null просто означает, что модель не была заполнена.

Ответ 1

Проблема в том, что у вас действительно есть три возможных значения; true, false и null, поэтому CheckBoxFor не может обрабатывать три состояния (только два состояния).

Брэд Уилсон обсуждает в своем блоге здесь. Он использует DropDownList для обнуляемых булевых элементов.

Этот StackOverflow question позволяет намного лучше описать ситуацию, чем я сделал выше. Недостатком решения иногда является значение nullable, которое не подразумевает false, оно должно быть недействительным. Примером этого могут служить критерии фильтрации, в которых вы не хотите применять true или false.

Ответ 2

Если вы не заботитесь о нулевом значении и просто хотите, чтобы флажок не был отмечен при его нулевом значении, вы можете сделать следующее:

Создайте другое свойство типа bool в вашей модели следующим образом:

public bool NotNullableBool
{
    get
    {
        return NullableBool == true;
    }
    set
    {
        NullableBool = value;
    }
}

Тогда просто используйте это для привязки...

Ответ 3

Для меня это намного лучше:

<%= Html.CheckBox("IsDefault", Model.IsDefault.HasValue? Model.IsDefault : false) %>

Ответ 4

Здесь, как сопоставить булевое логическое свойство bool? в DropDownListFor:

@model SomeModel

<!-- ...some HTML... -->

@Html.DropDownListFor(m => m.NullableBooleanProperty, new SelectList(
        new[] { 
            new { Value = "", Text = "-- Choose YES or NO --" },
            new { Value = "true", Text = "YES" },
            new { Value = "false", Text = "NO" },
        },
        "Value",
        "Text"
    ))

И вот как сопоставить его с CheckBoxFor с использованием свойства null-nullable proxy как обходного пути:

В ViewModel:

public bool NullableBooleanPropertyProxy
{
    get
    {
        return NullableBooleanProperty == true;
    }
    set
    {
        NullableBooleanProperty = value;
    }
}

В представлении:

@model SomeModel

<!-- ...some HTML... -->

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

Единственным недостатком этого обходного пути является то, что значение null будет считаться false: если вы не можете принять это, лучше использовать элемент управления, который может поддерживать три состояния, например вышеупомянутое DropDownListFor.

Для получения дополнительной информации читайте здесь.

Ответ 5

Чтобы добавить к ответу vapcguy, еще один "более чистый" способ сделать это, как следует

@Html.CheckBox("IsDefault", Model?.IsDefault)

или

<%= Html.CheckBox("IsDefault", Model?.IsDefault) %>

Ответ 6

Вы можете создать шаблон редактора, чтобы отобразить флажок для nullable Booleans. Назовите шаблон Boolean.cshtml, чтобы использовать его как значение по умолчанию для всех логических свойств внутри сайта. Убедитесь, что файл находится в папке ~/Views/Shared/EditorTemplates

@model bool?
@Html.CheckBox(String.Empty, Model??false)