2011-01-31 59 views
0

我写了一个辅助方法,在我的asp.net显示从我的模型枚举MVC应用程序在我的意见下拉列表。解决asp.net mvc的下拉列表中选择值超控器问题

这里是我的代码:

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); 

    } 

这实际上产生了选择项目列表:

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 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); 
    } 

现在我有问题描述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 2011-03-19 23:47:57