我正在尝试使用反射构建设置页面。一些选项是枚举,但标准@Html.EditorFor()
给出了一个文本框而不是这些属性的下拉列表。我有一种使用@Html.DropDownList()
进行排序的方法,但我希望“for”帮助程序能够获得预先选择值的好处。
public class CycleSettings
{
//a bunch of sub-objects, like:
public SurveyConfiguration Survey { get; set; }
}
public class SurveyConfiguration
{
[JsonConverter(typeof(StringEnumConverter))]
[DisplayName("Display Survey Data")]
public DataDisplayFullOptions Data { get; set; }
}
public enum DataDisplayFullOptions
{
Available,
[Display(Name = "Coming Soon")]
ComingSoon,
Report
}
@foreach (var property in typeof(CycleSettings).GetProperties()) {
object temp = property.GetValue(Model.Settings.CycleSettings[Model.CurrentYear][Model.CurrentCycle]);
@Html.Label(property.Name)
<div style="padding-left: 20px">
@foreach (var subprop in temp.GetType().GetProperties())
{
object temp2 = subprop.GetValue(temp);
var label = Attribute.GetCustomAttribute(subprop, typeof (DisplayNameAttribute));
@Html.Label(label != null ? ((DisplayNameAttribute)label).DisplayName : subprop.Name,new {@style="padding-right: 20px"})
@(temp2.GetType().IsEnum ? Html.EnumDropDownListFor((m) => temp2) : Html.EditorFor((m) => temp2)) //error occurs here on EnumDropDownListFor path
/*Html.DropDownList(subprop.Name, EnumHelper.GetSelectList(temp2.GetType()))*/ //this worked, but I am trying to use the EnumDropDownListFor to get the correct property selected on load
<br/>
}
</div>
}
[ArgumentException:不支持返回类型'System.Object'。 参数名称:表达式
System.Web.Mvc.Html.SelectExtensions.EnumDropDownListFor(HtmlHelper`1 htmlHelper,Expression`1表达式,String optionLabel,IDictionary`2 htmlAttributes)+1082
System.Web.Mvc.Html.SelectExtensions.EnumDropDownListFor(HtmlHelper`1 htmlHelper,Expression`1表达式,String optionLabel)+90
编辑:刚试过这个 - 没有更多错误,但仍未选择正确的值:
Html.DropDownListFor((m) => temp2, EnumHelper.GetSelectList(temp2.GetType()))
答案 0 :(得分:2)
答案结果非常简单。我接近这个尝试:
Html.DropDownListFor((m) => temp2, EnumHelper.GetSelectList(temp2.GetType()))
我只需要override GetSelectList
:
Html.DropDownListFor((m) => temp2, EnumHelper.GetSelectList(temp2.GetType(), (Enum)temp2))
答案 1 :(得分:0)
这是我经常使用的枚举扩展。希望它可以提供帮助。
public enum Gender
{
[EnumDescription("Not selected")]
NotSelected,
[EnumDescription("Male")]
Male,
[EnumDescription("Female")]
Female
}
在您的视图中(您可以省略“数据绑定”Knockout绑定)
@Html.DropDownList(
"gender",
SelectListExt.ToSelectList(typeof(Gender)),
new
{
data_bind = "value: Gender",
})
选择列表助手类:
public static class SelectListExt
{
public static SelectList ToSelectList(Type enumType)
{
return ToSelectList(enumType, String.Empty);
}
public static SelectList ToSelectList(Type enumType, string selectedItem)
{
List<SelectListItem> items = new List<SelectListItem>();
foreach (var item in Enum.GetValues(enumType))
{
FieldInfo fi = enumType.GetField(item.ToString());
var attribute = fi.GetCustomAttributes(typeof(EnumDescription), true).FirstOrDefault();
var title = attribute == null ? item.ToString() : ((EnumDescription)attribute).Text;
// uncomment to skip enums without attributes
//if (attribute == null)
// continue;
var listItem = new SelectListItem
{
Value = ((int)item).ToString(),
Text = title,
Selected = selectedItem == ((int)item).ToString()
};
items.Add(listItem);
}
return new SelectList(items, "Value", "Text", selectedItem);
}
}
属性本身:
public class EnumDescription : Attribute
{
public string Text { get; private set; }
public EnumDescription(string text)
{
this.Text = text;
}
}
您还可以使用我的扩展类将枚举转换为字符串描述:
public static class EnumExtensions
{
public static string ToDescription(this Enum enumeration)
{
Type type = enumeration.GetType();
MemberInfo[] memInfo = type.GetMember(enumeration.ToString());
if (null != memInfo && memInfo.Length > 0)
{
object[] attrs = memInfo[0].GetCustomAttributes(typeof(EnumDescription), false);
if (null != attrs && attrs.Length > 0)
return ((EnumDescription)attrs[0]).Text;
}
else
{
return "0";
}
return enumeration.ToString();
}
}
此代码并不完美,但它适用于我。随意重构和发布更新!