列挙型からSelectListItemを生成とか
列挙型プロパティのEditとかでDropdownを使いたいけどSelectListItemを毎回作るコードを書くのは面倒なのでユーティリティ化
public static class ViewHelper { public static IEnumerable<SelectListItem> toList<T>() where T : struct, IConvertible { if (!typeof(T).IsEnum) { throw new ArgumentException("T must be an enumerated type"); } List<SelectListItem> items = new List<SelectListItem>(); foreach (var v in Enum.GetValues(typeof(T))) { items.Add( new SelectListItem(){Value=((int)v).ToString(),Text = Enum.GetName(typeof(T),v)} ); } return items; } }
usage
@Html.DropDownListFor(model => model.modelType, ViewHelper.toList<ModelClass.ModelType>(), new { @class = "form-control" })
らくちん。
最初
public static IEnumerable<SelectListItem> toList<T>() where T : Enum{
としてたんだけど、
Constraint cannot be special class 'System.Enum'.
と怒られた。どうやらEnumは型パラメータ制約では使えないらしい。
Since Enum Type implements IConvertible interface, a better implementation should be something like this:
public T GetEnumFromString<T>(string value) where T : struct, IConvertible { if (!typeof(T).IsEnum) { throw new ArgumentException("T must be an enumerated type"); } //... }This will still permit passing of value types implementing IConvertible. The chances are rare though.
c# - Create Generic method constraining T to an Enum - Stack Overflow
とのことで。
改良
毎回Listを使うのが非常にダサいのでLinqっぽく
public static IEnumerable<SelectListItem> toList<T>() where T : struct, IConvertible { if (!typeof(T).IsEnum) { throw new ArgumentException("T must be an enumerated type"); } return Enum.GetValues(typeof(T)).OfType<IConvertible>() .Select(v => new SelectListItem() { Value = v.ToInt32(System.Globalization.CultureInfo.CurrentCulture).ToString(), Text = Enum.GetName(typeof(T), v) }); }
Enum.GetValues()は非ジェネリックの配列が戻るのでOfTypeで''IConvertible''配列に変換。
((ここでTに変換しちゃうと、TにEnumの型制約が無いのでIntに変換できなくなる(の?)))
で、これをSelectで一気にSelectListItemにすると。