Enum DisplayName: шаблоны могут использоваться только с полевым доступом
Я знаю, что уже есть другие темы по этому поводу. Я их читаю. Вот что у меня есть:
namespace Books.Entities
{
public enum Genre
{
[Display(Name = "Non Fiction")]
NonFiction,
Romance,
Action,
[Display(Name = "Science Fiction")]
ScienceFiction
}
}
Модель:
namespace Books.Entities
{
public class Book
{
public int ID { get; set; }
[Required]
[StringLength(255)]
public string Title { get; set; }
public Genre Category { get; set; }
}
}
Затем, в представлении:
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Category)
</td>
</tr>
Я думаю, что фреймворк будет использовать свойство DisplayName автоматически. Кажется странным, что это не так. Но что угодно. Пытаясь преодолеть это с помощью расширения (нашел это в другой теме по тому же вопросу)...
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
public static class EnumExtensions
{
public static string GetDisplayName(this Enum enumValue)
{
return enumValue.GetType()
.GetMember(enumValue.ToString())
.First()
.GetCustomAttribute<DisplayAttribute>()
.GetName();
}
}
Похоже, это должно работать, но когда я пытаюсь использовать это:
@Html.DisplayFor(modelItem => item.Category.GetDispayName())
Я получаю эту ошибку:
{"Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions."}
2 ответа
Одна вещь, которую вы могли бы рассмотреть, это добавить DisplayTemplate для Enum и ваш @Html.DiplayFor()
будет использовать это.
Если вы создаете папку в вашем ~/Views/Shared
папка называется DisplayTemplates
, добавьте новое представление с именем Enum.cshtml и добавьте этот код в представление
@model Enum
@{
var display = Model.GetDisplayName();
}
@display
Тогда все, что вам нужно сделать, это использовать @Html.DisplayFor(modelItem => item.Category)
в других ваших взглядах.
Кстати ваш GetDisplayName
Код выдаст ошибку, если нет атрибута описания, так что вы можете использовать что-то вроде
public static string GetDisplayName(this Enum enumValue)
{
Type type = enumValue.GetType();
string name = Enum.GetName(type, enumValue);
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 name;
}
Хорошо, нашел пару способов обойти это. Во-первых, как предложил mxmissile, просто используйте:
@item.Category.GetDisplayName()
Оказывается, сообщение об ошибке говорит мне именно то, что мне нужно было знать. Я просто не понял, что @Html.DisplayFor() - это шаблон, и я не могу использовать его с расширением помощника.
Но лучшее решение оказалось тем, которое я нашел здесь:
http://www.codeproject.com/Articles/776908/Dealing-with-Enum-in-MVC
В этом решении автор предоставляет шаблон отображения, который работает по умолчанию для всех перечислений, без необходимости задавать GetDisplayName(). С этим решением оригинальный код работает просто отлично:
@Html.DisplayFor(modelItem => item.Category)
И более того, по умолчанию это будет работать по всем направлениям.
(ПРИМЕЧАНИЕ: все это предполагает, что вы используете MVC5.x)