2012-09-21 69 views
2

我有一個網頁,其下拉列表由枚舉填充。MVC Model.IsValid枚舉

public enum RegionType 
{ 
    State, 
    [System.Xml.Serialization.XmlEnumAttribute("County/District")] 
    County_District, 
    [System.Xml.Serialization.XmlEnumAttribute("City/Town")] 
    City_Town, 
    Municipality, 
    Village 
} 

下拉實際上是通過下面的方法表達了枚舉:

public static List<string> GetRegionTypes() 
{ 
    List<string> theReturn = new List<string>(); 
    theReturn.Add(""); 
    foreach (RegionType s in Enum.GetValues(typeof(RegionType))) { 
     theReturn.Add(GetXmlEnumValue(s)); 
    } 
    return theReturn; 
} 

的偉大工程,在下拉菜單中顯示了正確的價值觀和一切。問題在於我有'xmlenum'屬性的2個值。如果我選擇區域類型'國家/地區'或'城市/城鎮',則該模型的'RegionType'屬性無法將其轉換爲MVC控制器POST操作中的對應枚舉。我如何才能正確地進行翻譯?

回答

1

你可以定義下面的擴展方法,將枚舉類型轉換成可以由DropDownListFor助手可以使用的SelectList:

public static class EnumExtensions 
{ 
    public static SelectList ToSelectList<TEnum>(this TEnum enumObj) 
    { 
     var enumType = typeof(TEnum); 
     if (enumType.IsGenericType && enumType.GetGenericTypeDefinition() == typeof(Nullable<>)) 
     { 
      enumType = enumType.GetGenericArguments()[0]; 
     } 

     var fields = enumType.GetFields(
      BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public 
     ); 
     var values = Enum.GetValues(enumType).OfType<TEnum>(); 
     var items = 
      from value in values 
      from field in fields 
      let xmlEnumAttribute = field 
       .GetCustomAttributes(
        typeof(XmlEnumAttribute), true 
       ) 
       .OfType<XmlEnumAttribute>() 
       .FirstOrDefault() 
      let name = (xmlEnumAttribute != null) 
       ? xmlEnumAttribute.Name 
       : value.ToString() 
      where value.ToString() == field.Name 
      select new { Id = value, Name = name }; 
     return new SelectList(items, "Id", "Name", enumObj); 
    } 
} 

然後很容易。你有一個視圖模型:

public class MyViewModel 
{ 
    [Required] 
    public RegionType? Region { get; set; } 
} 

控制器:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     var model = new MyViewModel 
     { 
      Region = RegionType.City_Town 
     }; 
     return View(model); 
    } 

    [HttpPost] 
    public ActionResult Index(MyViewModel model) 
    { 
     if (!ModelState.IsValid) 
     { 
      return View(model); 
     } 
     return Content("Thanks for choosing " + model.Region.Value.ToString()); 
    } 
} 

和視圖:

@model MyViewModel 

@using (Html.BeginForm()) 
{ 
    @Html.DropDownListFor(x => x.Region, Model.Region.ToSelectList(), "-- Region --") 
    @Html.ValidationMessageFor(x => x.Region) 
    <button type="submit">OK</button> 
} 
+0

的偉大工程!謝謝 – Phil

0

如果僅用於顯示的目的,我們使用Description屬性,(witin使用System.ComponentModel):

public enum SelectedAddressType 
{ 
    [Description("Primary Site")] 
    PrimarySite = 1, 

    [Description("Registered Office")] 
    RegisteredOffice = 2, 

    [Description("Alternative Invoice Address")] 
    Alternative = 3 
} 

與顯示它:

@Html.EnumDropDownListFor(model => model.SelectedInvoiceAddress, new { id = "selInvAdd" }, "Select") 

這個幫手:

public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes, string selectItem) 
    { 
     ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); 
     Type enumType = GetNonNullableModelType(metadata); 
     IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>(); 

     IEnumerable<SelectListItem> items = from value in values 
              select new SelectListItem 
              { 
               Text = GetEnumDescription(value), 
               Value = value.ToString(), 
               Selected = value.Equals(metadata.Model) 
              }; 

     // If the enum is nullable, add an 'empty' item to the collection 
     if (metadata.IsNullableValueType) 
      items = SingleEmptyItem.Concat(items); 

     if(!string.IsNullOrEmpty(selectItem)) 
      return htmlHelper.DropDownListFor(expression, items, selectItem, htmlAttributes); 

     return htmlHelper.DropDownListFor(expression, items, htmlAttributes); 
    }