2012-02-14 15 views
2

ドロップダウンリストに表示列挙を使用するための便利な拡張方法があります。例えば、hereおよびhereMVC3 EnumDropdownListの選択値

しかし、遭遇する1つの問題があります。つまり、列挙型がDescription属性で装飾されている場合、これらのヘルパーは機能しません。最初の例は、Description属性で完全に機能しますが、選択した値は設定されません。 2番目の例では、選択した値を設定しますが、description属性は使用しません。だから、私は両方のメソッドを正しく動作するヘルパーに結合する必要があります。私はそれを働かせるために多くのバリエーションを持っていますが、これまでの成功はありません。私は選択リストを作成するいくつかの方法を試しましたが、何とかSelectedプロパティを無視します。私のすべてのテストでは、Selectedプロパティは1つの項目で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())); 
    } 
+0

jsut詳細情報:http://coding-in.net/asp-net-mvc-3-method-extension/ – mbowles

答えて

3

私が実際にカスタム値を持っていた列挙型と同じ問題が何を私が見つけたことは、私が使用している場合ということです

public enum Occupation 
{ 
    [Description("Lorry driver")] LorryDriver = 10, 
    [Description("The big boss")] Director = 11, 
    [Description("Assistant manager")] AssistantManager = 12 
} 

を設定していましたDropDownListFor()では、選択されたオプションを設定するためにSelectListItemコレクションから選択された項目を使用しません。代わりに、バインドしようとしているプロパティ(m => m.Occupation)と等しい値を持つオプションを選択します。このため、enumの実際の整数値ではなく、その列挙型の.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) 
+0

ありがとうございました。たとえコードが実際に私のために働かなかったとしても、問題を解決するのに役立ちました!私はまだ最終的にトリックを行ったかどうかはわかりません。あなたのコメントに従ってToSelectList関数を修正し、GetDescriptionメソッドと組み合わせました。 – Hanno

1

が作業を行うソリューションを要約します(私にとっては少なくとも):

私は以下のヘルパーメソッドのセットを使用します

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) 

これはdescription属性を伴うまたは伴わない列挙で動作し、正しい選択された値を設定します。

+0

GetDescription()(上記のZenoから簡単にコピー)がありますが、 'htmlHelper.DropDownList'はMVC3プロジェクトでは定義されておらず、VSはどこにあるのかわからない(私は既にSystem.Webを使っています。 Mvc')なので、どういう問題があるのか​​分かりません。そのメソッドの名前空間は何ですか? –

関連する問題