我自己做了一個擴展方法,我現在在每一個項目中使用:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.Mvc;
namespace App.Extensions
{
public static class EnumExtensions
{
public static SelectList ToSelectList(Type enumType)
{
return new SelectList(ToSelectListItems(enumType));
}
public static List<SelectListItem> ToSelectListItems(Type enumType, Func<object, bool> itemSelectedAction = null)
{
var arr = Enum.GetValues(enumType);
return (from object item in arr
select new SelectListItem
{
Text = ((Enum)item).GetDescriptionEx(typeof(MyResources)),
Value = ((int)item).ToString(),
Selected = itemSelectedAction != null && itemSelectedAction(item)
}).ToList();
}
public static string GetDescriptionEx(this Enum @this)
{
return GetDescriptionEx(@this, null);
}
public static string GetDescriptionEx(this Enum @this, Type resObjectType)
{
// If no DescriptionAttribute is present, set string with following name
// "Enum_<EnumType>_<EnumValue>" to be the default value.
// Could also make some code to load value from resource.
var defaultResult = $"Enum_{@this.GetType().Name}_{@this}";
var fi = @this.GetType().GetField(@this.ToString());
if (fi == null)
return defaultResult;
var customAttributes = fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (customAttributes.Length <= 0 || customAttributes.IsNot<DescriptionAttribute[]>())
{
if (resObjectType == null)
return defaultResult;
var res = GetFromResource(defaultResult, resObjectType);
return res ?? defaultResult;
}
var attributes = (DescriptionAttribute[])customAttributes;
var result = attributes.Length > 0 ? attributes[0].Description : defaultResult;
return result ?? defaultResult;
}
public static string GetFromResource(string defaultResult, Type resObjectType)
{
var searchingPropName = defaultResult;
var props = resObjectType.GetProperties();
var prop = props.FirstOrDefault(t => t.Name.Equals(searchingPropName, StringComparison.InvariantCultureIgnoreCase));
if (prop == null)
return defaultResult;
var res = prop.GetValue(resObjectType) as string;
return res;
}
public static bool IsNot<T>(this object @this)
{
return !(@this is T);
}
}
}
,然後用它像這樣(在視圖中。例如cshtml)(爲了清晰起見,代碼在兩行中被打破;也可以打上鍊接):
// A SelectList without default value selected
var list1 = EnumExtensions.ToSelectListItems(typeof(occupancyTimeline));
@Html.DropDownListFor(model => model.occupancyTimeline, new SelectList(list1), "")
// A SelectList with default value selected if equals "DesiredValue"
// Selection is determined by lambda expression as a second parameter to
// ToSelectListItems method which returns bool.
var list2 = EnumExtensions.ToSelectListItems(typeof(occupancyTimeline), item => (occupancyTimeline)item == occupancyTimeline.DesiredValue));
@Html.DropDownListFor(model => model.occupancyTimeline, new SelectList(list2), "")
更新
基於菲爾的建議下,我上面的代碼的可能性更新到一些資源讀枚舉的顯示值(如果您有任何)。資源中的項目名稱應採用Enum_<EnumType>_<EnumValue>
(例如Enum_occupancyTimeline_TwelveMonths
)的格式。通過這種方式,您可以在資源文件中爲您的枚舉值提供文本,而無需使用某些屬性修飾枚舉值。資源類型(MyResource)直接包含在ToSelectItems方法中。您可以將其作爲擴展方法的參數提取。
命名枚舉值的另一種方式是應用Description屬性(這個工作方式沒有使代碼適應我所做的更改)。例如:
public enum occupancyTimeline
{
[Description("12 Months")]
TwelveMonths,
[Description("14 Months")]
FourteenMonths,
[Description("16 Months")]
SixteenMonths,
[Description("18 Months")]
EighteenMonths
}
你的意思是顯示在你的下拉菜單中? –
顯示在下拉菜單中,作爲它的值 – user979331
不幸的是,沒有設置枚舉'.ToString()'函數,我相信。 –