MVC3 EnumDropdownList selected value
本文关键字:value selected EnumDropdownList MVC3 | 更新日期: 2023-09-27 18:24:48
对于在下拉列表中显示枚举,有一些有用的扩展方法。例如这里和这里。
但我遇到了一个问题,那就是如果使用Description属性修饰枚举,那么这些助手就不起作用。第一个示例可以完美地使用"描述"属性,但它没有设置选定的值。第二个示例设置选定的值,但不使用description属性。因此,我需要将这两种方法组合成一个工作助手,以正确地完成这两种工作。我有很多变化来让它发挥作用,但到目前为止还没有成功。我尝试了几种方法来创建一个selectlist,但不知怎么的,它忽略了Selected属性。在我的所有测试中,有一项的Selected属性设置为true,但该属性被忽略。所以任何想法都是最受欢迎的!
这是我尝试过的最新代码:
public static IEnumerable<SelectListItem> 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(DescriptionAttribute), true).FirstOrDefault();
var title = attribute == null ? item.ToString() : ((DescriptionAttribute)attribute).Description;
var listItem = new SelectListItem
{
Value = ((int)item).ToString(),
Text = title,
Selected = selectedItem == item.ToString()
};
items.Add(listItem);
}
return items;
}
public static HtmlString EnumDropDownList2For<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> modelExpression)
{
var typeOfProperty = modelExpression.ReturnType;
if (!typeOfProperty.IsEnum)
throw new ArgumentException(string.Format("Type {0} is not an enum", typeOfProperty));
var value = htmlHelper.ViewData.Model == null
? default(TProperty)
: modelExpression.Compile()(htmlHelper.ViewData.Model);
return htmlHelper.DropDownListFor(modelExpression, ToSelectList(modelExpression.ReturnType, value.ToString()));
}
我在枚举中遇到了同样的问题,它实际上有自定义值集
public enum Occupation
{
[Description("Lorry driver")] LorryDriver = 10,
[Description("The big boss")] Director = 11,
[Description("Assistant manager")] AssistantManager = 12
}
我发现,当我使用DropDownListFor()时,它不会使用SelectListItem集合中的选定项来设置选定选项。相反,它选择了一个值等于我试图绑定到的属性(m=>m.Occupation)的选项,为此它使用枚举的.ToString(),而不是枚举的实际整数值。因此,我最终将SelectListItem的值设置为:
var listItem = new SelectListItem
{
Value = item.ToString(), // use item.ToString() instead
Text = title,
Selected = selectedItem == item.ToString() // <- no need for this
};
辅助方法:
public static class SelectListItemsForHelper
{
public static IEnumerable<SelectListItem> SelectListItemsFor<T>(T selected) where T : struct
{
Type t = typeof(T);
if (t.IsEnum)
{
return Enum.GetValues(t).Cast<Enum>().Select(e => new SelectListItem { Value = e.ToString(), Text = e.GetDescription() });
}
return null;
}
public static string GetDescription<TEnum>(this TEnum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
if (fi != null)
{
var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Length > 0)
return attributes[0].Description;
}
return value.ToString();
}
}
视图中:
@Html.DropDownListFor(m => m.Occupation, SelectListItemsForHelper.SelectListItemsFor(Model.Occupation), String.Empty)
总结有效的解决方案(至少对我来说):
我使用以下一组辅助方法
public static IEnumerable<SelectListItem> ToSelectList(Type enumType, string selectedItem)
{
List<SelectListItem> items = new List<SelectListItem>();
foreach (var item in Enum.GetValues(enumType))
{
var title = item.GetDescription();
var listItem = new SelectListItem
{
Value = item.ToString(),
Text = title,
Selected = selectedItem == item.ToString()
};
items.Add(listItem);
}
return items;
}
public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) where TModel : class
{
string inputName = GetInputName(expression);
var value = htmlHelper.ViewData.Model == null
? default(TProperty)
: expression.Compile()(htmlHelper.ViewData.Model);
return htmlHelper.DropDownList(inputName, ToSelectList(typeof(TProperty), value.ToString()));
}
public static string GetInputName<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression)
{
if (expression.Body.NodeType == ExpressionType.Call)
{
MethodCallExpression methodCallExpression = (MethodCallExpression)expression.Body;
string name = GetInputName(methodCallExpression);
return name.Substring(expression.Parameters[0].Name.Length + 1);
}
return expression.Body.ToString().Substring(expression.Parameters[0].Name.Length + 1);
}
private static string GetInputName(MethodCallExpression expression)
{
MethodCallExpression methodCallExpression = expression.Object as MethodCallExpression;
if (methodCallExpression != null)
{
return GetInputName(methodCallExpression);
}
return expression.Object.ToString();
}
用法:
@Html.EnumDropDownListFor(m => m.MyEnumType)
这适用于带有或不带有描述属性的枚举,并设置正确的选定值。