2011-01-31 24 views
0

私のビューのドロップダウンリストとして、自分のasp.net MVCアプリケーションで私のモデルから列挙型を表示するヘルパーメソッドを書きました。今、私はasp.net mvcドロップダウンリストの値を選択した値オーバーライダーの問題

 public static MvcHtmlString EnumDropDownList<TEnum>(this HtmlHelper htmlHelper, 
                 object enumObj, 
                 string name, 
                 string defaultItemKey, 
                 bool sortAlphabetically, 
                 object firstValueOverride, 
                 object htmlAttributes) 
    where TEnum : struct 
    { 
     return htmlHelper.DropDownList(name, 
             CreateSelectItemList<TEnum>(enumObj, 
                   defaultItemKey, 
                   sortAlphabetically, 
                   firstValueOverride), 
             htmlAttributes); 
    } 

public static List<SelectListItem> ToSelectList<T>(
    this IEnumerable<T> enumerable, 
    Func<T, string> text, 
    Func<T, string> value, 
    string defaultOption, 
    object selectedVal, 
    bool sortAlphabetically, 
    object FirstValueOverride) 
{ 

    int iSelectedVal = -1; 

    if(selectedVal!=null) 
    { 
     try 
     { 
      iSelectedVal = Convert.ToInt32(selectedVal); 
     } 
     catch 
     { 
     } 
    } 

    var items = enumerable.Select(f => new SelectListItem() 
    { 
     Text = text(f), 
     Value = value(f), 
     Selected = (iSelectedVal > -1)? (iSelectedVal.ToString().Equals(value(f))) : false 
    }); 

    #region Sortare alfabetica 
    if (sortAlphabetically) 
     items = items.OrderBy(t => t.Text); 
    #endregion Sortare alfabetica 

    var itemsList = items.ToList(); 

    Func<SelectListItem, bool> funct = null; 
    string sValue = string.Empty; 
    SelectListItem firstItem = null; 
    SelectListItem overridenItem = null; 
    int overridenIndex = 0; 

    if (FirstValueOverride != null) 
    { 
     sValue = FirstValueOverride.ToString(); 

     funct = (t => t.Value == sValue); 
     overridenItem = itemsList.SingleOrDefault(funct); 
     overridenIndex = itemsList.IndexOf(overridenItem); 

     if (overridenItem != null) 
     { 
      firstItem = itemsList.ElementAt(0); 
      itemsList[0] = overridenItem; 
      itemsList[overridenIndex] = firstItem; 
     } 
    } 

    if(!string.IsNullOrEmpty(defaultOption)) 
     itemsList.Insert(0, new SelectListItem() 
     { 
      Text = defaultOption, 
      Value = "-1" 
     }); 

    return itemsList; 
} 

これらは私が呼び出すメソッドです:これは、実際に選択項目のリストを生成し

public static List<SelectListItem> CreateSelectItemList<TEnum>(object enumObj, 
                  string defaultItemKey, 
                  bool sortAlphabetically, 
                  object firstValueOverride) 
    where TEnum : struct 
    { 
     var values = (from v in (TEnum[])Enum.GetValues(typeof(TEnum)) 
         select new 
         { 
          Id = Convert.ToInt32(v), 
          Name = ResourceHelpers.GetResourceValue(AppConstants.EnumResourceNamespace, 
                    typeof(TEnum).Name, v.ToString()) 
         }); 


     return values.ToSelectList(e => e.Name, 
               e => e.Id.ToString(), 
               !string.IsNullOrEmpty(defaultItemKey) ? ResourceHelpers.GetResourceValue(AppConstants.EnumResourceNamespace, defaultItemKey) : string.Empty, 
               enumObj, 
               sortAlphabetically, 
               firstValueOverride); 

    } 

:ここ

はそのために私のコードです記載された問題を有する here
私はこのヘルパーメソッドを呼び出し、入力の名前は選択された値が選択されないプロパティの名前と同じです。
そこに記載されている代替の解決策は私のためには機能しません。唯一の解決策は、名前を変更し、代わりにFormCollectionを使用してモデルバインドを使用しないことです。 ViewModelパターンを使用して検証を使用することができず、すべての列挙に対して追加のコードを記述する必要があるため、この回避策が嫌いです。
これをどうにかして補うためにカスタムモデルのバインダーを書きましたが、アクションを開始するときにそこでオーバーライドできるメソッドはありません。

FormCollectionを使用せずにこれを行う方法はありますか? 入力フィールドに値を入力して正しい値を選択しようとすると、何とかASP.NET MVCをインターセプトできますか?

ありがとうございます。

答えて

0

私は今sollutionを持って
ここではEnumDropDownListのコードで他の関数を関数は、質問に記載されています:

public static MvcHtmlString EnumDropDownList(this HtmlHelper htmlHelper, 
                object enumObj, 
                string name, 
                string defaultItemKey, 
                bool sortAlphabetically, 
                object firstValueOverride, 
                object htmlAttributes) 
{ 

    StringBuilder sbRezultat = new StringBuilder(); 

    int selectedIndex = 0; 

    var selectItemList = new List<SelectListItem>(); 


    if (enumObj != null) 
    { 
     selectItemList = CreateSelectItemList(enumObj, defaultItemKey, true, null); 

     var selectedItem = selectItemList.SingleOrDefault(item => item.Selected); 
     if (selectedItem != null) 
     { 
      selectedIndex = selectItemList.IndexOf(selectedItem); 

     } 
    } 

    var dict = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); 


    TagBuilder tagBuilder = new TagBuilder("select"); 

    tagBuilder.MergeAttribute("name", name,true); 

    bool bReadOnly = false; 

    //special case for readonly 
    if(dict.ContainsKey("readonly")) 
    { 
     //remove this tag it won't work the way mvc renders it anyway 
     dict.Remove("readonly"); 
     bReadOnly = true; 
    } 

    //in case the style element is completed if the drop down is not readonly 
    tagBuilder.MergeAttributes(dict, true); 

    if (bReadOnly) 
    { 
     //add a small javascript to make it readonly and add the lightgrey style 
     tagBuilder.MergeAttribute("onchange", "this.selectedIndex=" + selectedIndex + ";",true); 
     tagBuilder.MergeAttribute("style", "background: lightgrey", true); 
    } 

    sbRezultat.Append(tagBuilder.ToString(TagRenderMode.StartTag)); 


    foreach (var option in selectItemList) 
    { 
     sbRezultat.Append(" <option value='"); 
     sbRezultat.Append(option.Value); 
     sbRezultat.Append("' "); 
     if (option.Selected) 
      sbRezultat.Append("selected"); 
     sbRezultat.Append(" >"); 
     sbRezultat.Append(option.Text); 


     sbRezultat.Append("</option>"); 
    } 
    sbRezultat.Append("</select>"); 
    return new MvcHtmlString(sbRezultat.ToString()); 
} 

私も(EnumDropDownFor)のための型の一般的な機能を書いた:

public static MvcHtmlString EnumDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TProperty>> expression, 
           string defaultItemKey, 
           bool sortAlphabetically, 
           object firstValueOverride, 
           object htmlAttributes) 
    where TProperty : struct 
{ 
    string inputName = GetInputName(expression); 

    object selectedVal = null; 
    try 
    { 
     selectedVal = htmlHelper.ViewData.Model == null 
      ? default(TProperty) 
      : expression.Compile()(htmlHelper.ViewData.Model); 
    } 
    catch//in caz ca e ceva null sau ceva de genu' 
    { 
    } 

    return EnumDropDownList(htmlHelper, 
          selectedVal, 
          inputName, 
          defaultItemKey, 
          sortAlphabetically, 
          firstValueOverride, 
          htmlAttributes); 
} 

といくつかのヘルパーメソッド:

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(); 
} 
+0

MvcHtmlString(String)コンストラクタは廃止されました。代わりにMvcHtmlString.Create(String)を使用してください。 – OneDeveloper

関連する問題