MVC3 EditorTemplate для обнуляемого логического значения с использованием RadioButtons - PullRequest
19 голосов
/ 19 июля 2011

У меня есть свойство для одного из моих объектов, которое имеет логическое значение null. Я хочу, чтобы в моей логике значение true представляло Да, false - Нет, а 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 не будет правильно устанавливать свойство selected из-за проверки, которая выполняется для проверки того, что имя не пустое или не пустое (см. MVC3 source, InputExtensions.cs: строка # 259). Я не могу установить динамически проверяемый атрибут, сравнивая его с моделью, потому что браузер проверяет радиокнопку на наличие проверяемого атрибута, а не его значения, поэтому даже если мои радиокнопки выглядят так, как показано ниже, последняя из них остается выбранной .

<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>&nbsp;</div>

Я не могу условно добавить атрибут HtmlAttribute, используя что-то вроде if?truevalue:falsevalue, потому что части true / false будут разных анонимных типов, и я получаю ошибку.

Я борюсь за то, как это сделать, и надеюсь, у кого-нибудь из вас есть предложение, как решить эту проблему?

Ответы [ 6 ]

27 голосов
/ 22 июля 2011
@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>
2 голосов
/ 16 сентября 2015

Проблема в том, что вам нужно установить атрибут checked, потому что Html.RadioButtonFor не проверяет переключатель на основе обнуляемого значения bool (которое кажется недостатком).

Также путем установкипереключатели внутри тега метки, вы можете выбрать значение, щелкнув метку.

Shared / EditorTemplates / Boolean.cshtml

@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>
2 голосов
/ 26 декабря 2012

Как насчет того, чтобы какой-то метод расширения был интересен, чтобы сохранить эту "одну строку, чтобы управлять ими всеми".: -)

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>
1 голос
/ 17 апреля 2013

Вам просто нужно обработать специальный нулевой регистр, например:

<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>
0 голосов
/ 24 апреля 2019

с использованием Canvas Пример выше Я создал модель настройки и представление, чтобы вы могли управлять значениями с помощью модели и редактировать их в коде, bools не всегда да / нет / (н / д) Вот как это выглядит в MVC5.

с использованием универсальной модели для допускаемого значения bool

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")

И приведенные примеры вывода

Rendered html example

0 голосов
/ 08 июня 2017

Вы можете использовать @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>
}
...