MVC5: переключатель Enum с меткой в качестве отображаемого имени
У меня есть эти перечисления
public enum QuestionStart
{
[Display(Name="Repeat till common match is found")]
RepeatTillCommonIsFound,
[Display(Name="Repeat once")]
RepeatOnce,
[Display(Name="No repeat")]
NoRepeat
}
public enum QuestionEnd
{
[Display(Name="Cancel Invitation")]
CancelInvitation,
[Display(Name="Plan with participants on first available common date")]
FirstAvailableCommon,
[Display(Name="Plan with participants on my first available common date")]
YourFirstAvailableCommon
}
и у меня есть вспомогательный класс, чтобы показать всю радиообъект для каждого поля в перечислении
@model Enum
@foreach (var value in Enum.GetValues(Model.GetType()))
{
@Html.RadioButtonFor(m => m, value)
@Html.Label(value.ToString())
<br/>
}
В настоящий момент метка установлена на имя значения, а не на отображаемое имя, которое я дал для значений.
Например, для:
[Display(Name="Cancel Invitation")]
CancelInvitation
Я получаю радиокнопку с CancelInvitation
рядом с ней.
Как я могу отобразить отображаемое имя (Cancel Invitation
), которое я ему дал?
Ответы
Ответ 1
Здесь идет решение -
Кредит принадлежит этому экстраординарному джентльмену - ThumNet, который написал RadioButtonList для Enum в качестве расширения
Шаг 1 - Создайте файл RadioButtonListEnum.cshtml с приведенным ниже кодом (код из ссылки выше) в каталоге Views/Shared/EditorTemplates (если не существует, затем создайте этот каталог) -
@model Enum
@{
// Looks for a [Display(Name="Some Name")] or a [Display(Name="Some Name", ResourceType=typeof(ResourceFile)] Attribute on your enum
Func<Enum, string> getDescription = en =>
{
Type type = en.GetType();
System.Reflection.MemberInfo[] memInfo = type.GetMember(en.ToString());
if (memInfo != null && memInfo.Length > 0)
{
object[] attrs = memInfo[0].GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.DisplayAttribute),
false);
if (attrs != null && attrs.Length > 0)
return ((System.ComponentModel.DataAnnotations.DisplayAttribute)attrs[0]).GetName();
}
return en.ToString();
};
var listItems = Enum.GetValues(Model.GetType()).OfType<Enum>().Select(e =>
new SelectListItem()
{
Text = getDescription(e),
Value = e.ToString(),
Selected = e.Equals(Model)
});
string prefix = ViewData.TemplateInfo.HtmlFieldPrefix;
int index = 0;
ViewData.TemplateInfo.HtmlFieldPrefix = string.Empty;
foreach (var li in listItems)
{
string fieldName = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}_{1}", prefix, index++);
<div class="editor-radio">
@Html.RadioButton(prefix, li.Value, li.Selected, new { @id = fieldName })
@Html.Label(fieldName, li.Text)
</div>
}
ViewData.TemplateInfo.HtmlFieldPrefix = prefix;
}
Затем укажите свой enum -
public enum QuestionEnd
{
[Display(Name = "Cancel Invitation")]
CancelInvitation,
[Display(Name = "Plan with participants on first available common date")]
FirstAvailableCommon,
[Display(Name = "Plan with participants on my first available common date")]
YourFirstAvailableCommon
}
Шаг 2 - Создать модель -
public class RadioEnumModel
{
public QuestionEnd qEnd { get; set; }
}
Шаг 3 - Создание действия контроллера -
public ActionResult Index()
{
RadioEnumModel m = new RadioEnumModel();
return View(m);
}
Шаг 4 - Создать представление -
@model MVC.Controllers.RadioEnumModel
@Html.EditorFor(x => x.qEnd, "RadioButtonListEnum")
Тогда выход будет -
![enter image description here]()
Ответ 2
Я нашел некоторые из этих ответов запутанными, так я достиг результата. Надеюсь, это поможет кому-то еще.
Перетащите это в файл методов расширения:
public static string GetDescription(this Enum value)
{
Type type = value.GetType();
string name = Enum.GetName(type, value);
if (name != null)
{
FieldInfo field = type.GetField(name);
if (field != null)
{
DescriptionAttribute attr =
Attribute.GetCustomAttribute(field,
typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attr != null)
{
return attr.Description;
}
}
}
return null;
}
Убедитесь, что вы добавили свойство, которое является тем же типом, что и ваше перечисление, в вашу фактическую модель, чтобы привязка переключателя привязывалась.
Создайте шаблон редактора для вашего конкретного перечисления. Тогда, на ваш взгляд, ссылайтесь на это так:
@Html.EditorFor(m => m.MyEnumTypePropertyName)
Затем добавьте следующее в свой редактор:
@using MyProject.ExtensionMethods;
@model MyProject.Models.Enums.MyEnumType
@foreach (MyEnumType value in Enum.GetValues(typeof(MyEnumType)))
{
<div>
@Html.Label(value.GetDescription())
@Html.RadioButtonFor(m => m, value)
</div>
}
Запомнить. Если по какой-либо причине вы не выбираете радиокнопку, значение по умолчанию для вашего свойства перечисления всегда будет первым в пакете (т.е. нолем), а не нулевым.
Ответ 3
Вы можете использовать следующий метод перегрузки.
@Html.Label(value.ToString(),"Cancel Invitation")
Это приведет к тому, что метка с указанным текстом меток будет предоставлена в качестве второго параметра в вышеуказанном вызове.
Ответ 4
Вот решение, которое использует метод расширения и шаблон редактора для создания группы радиостанций с локализованным именем из атрибута отображения.
Метод расширения
public static string DisplayName(this Enum enumValue)
{
var enumType = enumValue.GetType();
var memberInfo = enumType.GetMember(enumValue.ToString()).First();
if (memberInfo == null || !memberInfo.CustomAttributes.Any()) return enumValue.ToString();
var displayAttribute = memberInfo.GetCustomAttribute<DisplayAttribute>();
if (displayAttribute == null) return enumValue.ToString();
if (displayAttribute.ResourceType != null && displayAttribute.Name != null)
{
var manager = new ResourceManager(displayAttribute.ResourceType);
return manager.GetString(displayAttribute.Name);
}
return displayAttribute.Name ?? enumValue.ToString();
}
Пример
public enum IndexGroupBy
{
[Display(Name = "By Alpha")]
ByAlpha,
[Display(Name = "By Type")]
ByType
}
И вот его использование:
@IndexGroupBy.ByAlpha.DisplayName()
Шаблон редактора
Вот шаблон редактора, который можно использовать с вышеописанным методом расширения:
@model Enum
@{
var listItems = Enum.GetValues(Model.GetType()).OfType<Enum>().Select(e =>
new SelectListItem
{
Text = e.DisplayName(),
Value = e.ToString(),
Selected = e.Equals(Model)
});
var prefix = ViewData.TemplateInfo.HtmlFieldPrefix;
var index = 0;
ViewData.TemplateInfo.HtmlFieldPrefix = string.Empty;
foreach (var li in listItems)
{
var fieldName = string.Format(CultureInfo.InvariantCulture, "{0}_{1}", prefix, index++);
<div class="editor-radio">
@Html.RadioButton(prefix, li.Value, li.Selected, new {@id = fieldName})
@Html.Label(fieldName, li.Text)
</div>
}
ViewData.TemplateInfo.HtmlFieldPrefix = prefix;
}
И вот пример использования:
@Html.EditorFor(m => m.YourEnumMember, "Enum_RadioButtonList")