Флажок для обнуляемого логического - PullRequest
88 голосов
/ 27 июля 2011

У моей модели логическое значение, которое должно быть обнуляемым

public bool? Foo
{
   get;
   set;
}

так в моем Razor cshtml у меня есть

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

за исключением того, что это не работает. Ни один не делает кастинг с (bool). Если я сделаю

@Html.CheckBoxFor(m => m.Foo.Value)

, который не создает ошибку, но не связывает мою модель при публикации и foo имеет значение null. Каков наилучший способ отобразить Foo на странице и сделать его привязанным к моей модели в сообщении?

Ответы [ 17 ]

100 голосов
/ 28 июля 2011

Я получил его на работу с

@Html.EditorFor(model => model.Foo) 

, а затем создайте Boolean.cshtml в моей папке EditorTemplates и вставьте

@model bool?

@Html.CheckBox("", Model.GetValueOrDefault())

внутри.

39 голосов
/ 01 июня 2015

Найден ответ на аналогичный вопрос - Отображение Nullable Bool как CheckBox .Это очень просто и просто работает:

@Html.CheckBox("RFP.DatesFlexible", Model.RFP.DatesFlexible ?? false)
@Html.Label("RFP.DatesFlexible", "My Dates are Flexible")

Это похоже на принятый ответ от @afinkelstein, за исключением того, что нам не нужен специальный шаблон редактора

26 голосов
/ 20 июня 2012

У меня 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> 
14 голосов
/ 27 июля 2011

У моей модели логическое значение, которое должно быть обнуляемым

Почему? Это не имеет смысла. Флажок имеет два состояния: отмечен / не отмечен, или True / False, если хотите. Там нет третьего государства.

Или подождать, когда вы используете модели доменов в своих представлениях вместо моделей представлений? Это твоя проблема. Поэтому для меня решение состоит в том, чтобы использовать модель представления, в которой вы определите простое логическое свойство:

public class MyViewModel
{
    public bool Foo { get; set; }
}

и теперь ваш контроллер будет передавать эту модель представления в вид и генерировать соответствующий флажок.

6 голосов
/ 02 мая 2012

Сложный примитив со скрытыми полями для выяснения, не рекомендуется ли False или Null.

Флажок - это не то, что вы должны использовать - он действительно имеет только одно состояние: Проверено . Иначе это может быть что угодно.

Когда поле вашей базы данных имеет логическое значение NULL (bool?), UX должен использовать 3-радио кнопки, где первая кнопка представляет ваш «Checked», вторая кнопка представляет «Not Checked», а третья кнопка представляет ваш 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 для переключения переключателей в горизонтальное положение (display: inline- блок), вертикальный или в табличном виде (отображение: встроенный блок; ширина: 100 пикселей;)

В модели (я использую строку, строку для определения словаря в качестве педагогического примера. Вы можете использовать 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());
}
}
3 голосов
/ 09 июня 2016

Самый чистый подход, который я мог бы предложить, - это расширить доступные расширения до HtmlHelper, в то же время повторно используя функциональные возможности, предоставляемые каркасом.прямой переход к нативному CheckBoxFor<Expression<Func<T, bool>>>, но я не думаю, что это возможно.

3 голосов
/ 09 июня 2015

Я бы на самом деле создал шаблон для него и использовал бы этот шаблон с EditorFor ().

Вот как я это сделал:

  1. Создать мой шаблон,который в основном является частичным представлением, которое я создал в каталоге 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;" />
    
  2. Используйте его следующим образом (в любом представлении):

    @Html.EditorFor (x => x.MyNullableBooleanCheckboxToBe, "CheckboxTemplate")

Это все.

Шаблоны являютсянастолько мощный в MVC, используйте их .. Вы можете создать целую страницу в качестве шаблона, который вы бы использовали с @Html.EditorFor();при условии, что вы передадите его модель представления в лямбда-выражении ..

3 голосов
/ 10 февраля 2014

Флажок предлагает только 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" });

View

@Html.DropDownListFor(m => m.myValue, valueList)
3 голосов
/ 08 ноября 2013

Для меня решение было изменить модель представления. Считайте, что вы ищете счета. Эти счета могут быть оплачены или нет. Таким образом, в вашем поиске есть три варианта: Платный, Неоплаченный или «Мне все равно».

Первоначально это было задано как 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)

Конечно, я завернул их в ярлыки и указал текст, я просто имею в виду еще один вариант.

1 голос
/ 27 июля 2011

У меня была похожая проблема в прошлом.

Создайте вход для флажка в HTML и установите атрибут name = "Foo".

<input type="checkbox" name="Foo" checked="@model.Foo.Value" /> Foo Checkbox<br />
...