คุณจะสร้างรายการดร็อปดาวน์จาก enum ใน ASP.NET MVC ได้อย่างไร


671

ฉันพยายามใช้Html.DropDownListวิธีการขยาย แต่ไม่สามารถหาวิธีใช้กับการแจงนับได้

สมมติว่าฉันมีการแจงนับเช่นนี้:

public enum ItemTypes
{
    Movie = 1,
    Game = 2,
    Book = 3
}

ฉันจะสร้างการดร็อปดาวน์ด้วยค่าเหล่านี้โดยใช้Html.DropDownListวิธีการขยายได้อย่างไร

หรือเป็นทางออกที่ดีที่สุดของฉันเพียงแค่สร้าง for loop และสร้างองค์ประกอบ Html ด้วยตนเอง

คำตอบ:


842

สำหรับ MVC v5.1 ให้ใช้ Html.EnumDropDownListFor

@Html.EnumDropDownListFor(
    x => x.YourEnumField,
    "Select My Type", 
    new { @class = "form-control" })

สำหรับ MVC v5 ให้ใช้ EnumHelper

@Html.DropDownList("MyType", 
   EnumHelper.GetSelectList(typeof(MyType)) , 
   "Select My Type", 
   new { @class = "form-control" })

สำหรับ MVC 5 และต่ำกว่า

ฉันย้อนคำตอบของ Rune ลงในวิธีการขยาย:

namespace MyApp.Common
{
    public static class MyExtensions{
        public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
            where TEnum : struct, IComparable, IFormattable, IConvertible
        {
            var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                select new { Id = e, Name = e.ToString() };
            return new SelectList(values, "Id", "Name", enumObj);
        }
    }
}

อนุญาตให้คุณเขียน:

ViewData["taskStatus"] = task.Status.ToSelectList();

โดย using MyApp.Common


13
ฉันไม่สามารถทำงานได้คุณช่วยได้ไหม เมื่อฉันทำ Post.PostType.ToSelectList (); มันไม่รู้จักนามสกุลหรือไม่
Barbaros Alp

3
ฉันไม่สามารถทำงานนี้ได้เช่นกัน สถานะ Enum Property ของคุณเป็นคลาสงานหรือไม่ นี่ไม่ใช่ค่าที่แจกแจงหรือไม่
Daryl

9
คุณสามารถ จำกัด ได้นิดหน่อยด้วย: where T: struct, IConvertible See: stackoverflow.com/questions/79126/…
Richard Garside

8
ที่นี่หนาว. หากใครกำลังดิ้นรนกับการใช้งานนี่เป็นวิธีที่ฉันทำ เพิ่มคลาส EnumHelpers ไปยังโฟลเดอร์ HtmlHelpers ใช้รหัสด้านบน เพิ่มเนมสเปซตามคำแนะนำ @TodK: <เพิ่มเนมสเปซ = "xxx.HtmlHelpers" /> จากนั้นฉันก็ใช้มันในหน้ามีดโกนเช่น: @ Html.DropDownListFor (model => model.Status, @ Model.Status.ToSelectList ()) HTH
Jeff Borden

6
โปรดทราบว่าในรุ่นที่ใหม่กว่าASP.NET MVCมีวิธีเนทีฟ: stackoverflow.com/a/22295360/1361084
Ofiris

359

ฉันรู้ว่าฉันมางานปาร์ตี้สายนี้ แต่คิดว่าคุณอาจพบว่าตัวแปรนี้มีประโยชน์เพราะอันนี้ยังช่วยให้คุณใช้สตริงที่เป็นคำอธิบายแทนค่าคงที่การแจงนับ เมื่อต้องการทำเช่นนี้ให้ตกแต่งรายการการแจงนับแต่ละรายการด้วยแอตทริบิวต์ [System.ComponentModel.Description]

ตัวอย่างเช่น:

public enum TestEnum
{
  [Description("Full test")]
  FullTest,

  [Description("Incomplete or partial test")]
  PartialTest,

  [Description("No test performed")]
  None
}

นี่คือรหัสของฉัน:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Reflection;
using System.ComponentModel;
using System.Linq.Expressions;

 ...

 private static Type GetNonNullableModelType(ModelMetadata modelMetadata)
    {
        Type realModelType = modelMetadata.ModelType;

        Type underlyingType = Nullable.GetUnderlyingType(realModelType);
        if (underlyingType != null)
        {
            realModelType = underlyingType;
        }
        return realModelType;
    }

    private static readonly SelectListItem[] SingleEmptyItem = new[] { new SelectListItem { Text = "", Value = "" } };

    public static string GetEnumDescription<TEnum>(TEnum value)
    {
        FieldInfo fi = value.GetType().GetField(value.ToString());

        DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

        if ((attributes != null) && (attributes.Length > 0))
            return attributes[0].Description;
        else
            return value.ToString();
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
    {
        return EnumDropDownListFor(htmlHelper, expression, null);
    }

    public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
    {
        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);

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

จากนั้นคุณสามารถทำสิ่งนี้ในมุมมองของคุณ:

@Html.EnumDropDownListFor(model => model.MyEnumProperty)

หวังว่านี่จะช่วยคุณได้!

** แก้ไข 2014 -JAN-23: Microsoft เพิ่งเปิดตัว MVC 5.1 ซึ่งตอนนี้มีคุณสมบัติ EnumDropDownListFor น่าเศร้าที่ดูเหมือนว่าจะไม่เคารพแอตทริบิวต์ [รายละเอียด] ดังนั้นโค้ดด้านบนยังคงอยู่ในส่วนดู Enum ในบันทึกย่อประจำรุ่นของ Microsoft สำหรับ MVC 5.1

อัปเดต: รองรับการแสดงผลของแอตทริบิวต์[Display(Name = "Sample")]เพื่อให้สามารถใช้งานได้

[อัปเดต - เพิ่งสังเกตสิ่งนี้และรหัสดูเหมือนว่าเป็นรุ่นเพิ่มเติมของรหัสที่นี่: https://blogs.msdn.microsoft.com/stuartleeks/2010/05/21/asp-net-mvc-creating-a- dropdownlist-helper-for-enums /พร้อมกับสองส่วนเพิ่มเติม ถ้าเป็นเช่นนั้นการระบุแหล่งที่มาจะดูยุติธรรม ;-)]


28
+1 ฉันพบสิ่งนี้มีประโยชน์ที่สุดสำหรับคำตอบทั้งหมดที่นี่ ฉันสามารถเปลี่ยนมันให้เป็นโค้ดที่สามารถนำกลับมาใช้ใหม่ได้สูง ขอบคุณ!
Ed Charbeneau

43
Visual Studio มีข้อผิดพลาดแปลก ๆ ที่ถ้าคุณไม่ได้อ้างอิงSystem.Web.Mvc.Htmlมันบอกว่าDropDownListForหาไม่พบ using System.Web.Mvc.Html;คุณต้องทำด้วยตนเอง เพียงเท่านี้คุณก็รู้
Kezzer

1
ฉันมีตัวแปรนี้ในส่วนสำคัญที่เราใช้ในโครงการทั้งหมดของเรา: gist.github.com/1287511
kamranicus

1
วิธีแก้ปัญหาที่ยอดเยี่ยมขอบคุณจะดียิ่งขึ้นถ้าคุณสามารถแคชผลลัพธ์ของ GetEnumDescription
M. Mennan Kara

17
MVC 5.1 EnumDropDownListFor ใหม่ไม่ได้ใช้ [คำอธิบาย ("")] แต่ใช้ [แสดง (ชื่อ = "")]! สนุก :)
Supergibbs

195

ในASP.NET MVC 5.1พวกเขาเพิ่มตัวEnumDropDownListFor()ช่วยดังนั้นไม่จำเป็นต้องมีส่วนขยายที่กำหนดเอง:

แบบ :

public enum MyEnum
{
    [Display(Name = "First Value - desc..")]
    FirstValue,
    [Display(Name = "Second Value - desc...")]
    SecondValue
}

ดู :

@Html.EnumDropDownListFor(model => model.MyEnum)

การใช้เครื่องช่วยแท็ก (ASP.NET MVC 6) :

<select asp-for="@Model.SelectedValue" asp-items="Html.GetEnumSelectList<MyEnum>()">

21
สิ่งนี้จะต้องถูกกระแทกไปจนถึงจุดแรกอย่างใด

3
คุณควรสร้างคำถามใหม่ที่เฉพาะเจาะจงกับ MVC 5.1 และใช้เป็นคำตอบจากนั้นส่งลิงก์ไปยังโพสต์ให้ฉัน
Kevin Heidt

2
สิ่งที่ฉันไม่ชอบเกี่ยวกับ EnumDropDownListFor () คือมันบันทึกลงใน DB ค่า int ของ enum ไม่ใช่ข้อความดังนั้นหากคุณเคยเลือกที่จะเพิ่มรายการ enum ใหม่มันจะต้องไปที่ส่วนท้ายของรายการ เพื่อหลีกเลี่ยงความสัมพันธ์ของค่า int ของฐานข้อมูลที่บันทึกไว้กับตำแหน่งดั้งเดิมของรายการ enum นั่นเป็นข้อ จำกัด ที่ไม่จำเป็นหากบันทึกข้อความไว้ นอกจากนี้ฉันสามารถดู db และดูข้อความได้แทนที่จะเป็น int ที่ฉันต้องค้นหาค่าข้อความที่อื่น มิฉะนั้นตัวช่วย html นี้จะสะดวกในการใช้
Giovanni

2
@Giovanni - คุณสามารถระบุค่าตัวเลขของคุณเอง
Tommy

1
@Giovanni การออกแบบที่เข้มงวดควรกำหนดค่าสำหรับแต่ละรายการ enum (ถ้าเป็นสิ่งสำคัญ) มิฉะนั้นค่าควรไม่สำคัญ (และการวางค่าใหม่ในตอนท้ายไม่ควรเป็นปัญหา) การบันทึกค่า int จะดีกว่าเมื่อบันทึกการจัดเก็บและเพิ่มประสิทธิภาพ (เมื่อทำการค้นหาบางอย่าง)
King King

130

ฉันชนกับปัญหาเดียวกันพบคำถามนี้และคิดว่าวิธีการแก้ปัญหาของ Ash ไม่ใช่สิ่งที่ฉันกำลังมองหา การสร้าง HTML เองหมายถึงความยืดหยุ่นน้อยลงเมื่อเทียบกับHtml.DropDownList()ฟังก์ชั่นในตัว

ปรากฎ C # 3 และอื่น ๆ ที่ทำให้สิ่งนี้เป็นเรื่องง่าย ฉันมีenumชื่อTaskStatus:

var statuses = from TaskStatus s in Enum.GetValues(typeof(TaskStatus))
               select new { ID = s, Name = s.ToString() };
ViewData["taskStatus"] = new SelectList(statuses, "ID", "Name", task.Status);

สิ่งนี้สร้าง ol ดี ' SelectListที่สามารถใช้เหมือนที่คุณคุ้นเคยในมุมมอง:

<td><b>Status:</b></td><td><%=Html.DropDownList("taskStatus")%></td></tr>

ประเภทที่ไม่ระบุชื่อและ LINQ ทำให้ IMHO ที่สง่างามยิ่งกว่านี้มาก ไม่มีเจตนากระทำผิดกฎหมาย Ash :)


คำตอบที่ดี! ฉันหวังว่าจะมีคนใช้ linq และ SelectList :) ดีใจที่ฉันตรวจสอบที่นี่ก่อน!
Pure.Krome

1
ID = s ให้ฉัน DataTextField ไม่ใช่ค่าหรือไม่ อะไรคือเหตุผล? ขอบคุณ
Barbaros Alp

1
รูนฉันใช้วิธีเดียวกันนี้และ DropDownList DOES จะแสดงผลเมื่อโพสต์ไปยังเซิร์ฟเวอร์มันไม่ได้บันทึกค่าที่ฉันเลือก
clockwiseq

5
@BarbarosAlp เพื่อให้ ID เป็นตัวเลขคุณจะต้องส่ง enum ไปยัง int:select new { ID = (int)s, Name = s.ToString() };
Keith

นี่คือคำตอบที่ฉันชอบที่สุดเพราะความเรียบง่าย ความอับอายที่คุณไม่ได้รับเครดิตเพียงพอเนื่องจากคำตอบที่เลือกใช้โซลูชันของคุณ
anar khalilov

63

นี่เป็นทางออกที่ดีกว่า:

https://www.spicelogic.com/Blog/enum-dropdownlistfor-asp-net-mvc-5

พูดที่นี่เป็นรูปแบบของคุณ:

ป้อนคำอธิบายรูปภาพที่นี่

ตัวอย่างการใช้งาน:

ป้อนคำอธิบายรูปภาพที่นี่

UI ที่สร้างขึ้น: ป้อนคำอธิบายรูปภาพที่นี่

และสร้าง HTML

ป้อนคำอธิบายรูปภาพที่นี่

ช็อตคัตซอร์สโค้ดของ Helper Extension:

ป้อนคำอธิบายรูปภาพที่นี่

คุณสามารถดาวน์โหลดโครงการตัวอย่างได้จากลิงค์ที่ฉันให้ไว้

แก้ไข: นี่คือรหัส:

public static class EnumEditorHtmlHelper
{
    /// <summary>
    /// Creates the DropDown List (HTML Select Element) from LINQ 
    /// Expression where the expression returns an Enum type.
    /// </summary>
    /// <typeparam name="TModel">The type of the model.</typeparam>
    /// <typeparam name="TProperty">The type of the property.</typeparam>
    /// <param name="htmlHelper">The HTML helper.</param>
    /// <param name="expression">The expression.</param>
    /// <returns></returns>
    public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression) 
        where TModel : class
    {
        TProperty value = htmlHelper.ViewData.Model == null 
            ? default(TProperty) 
            : expression.Compile()(htmlHelper.ViewData.Model);
        string selected = value == null ? String.Empty : value.ToString();
        return htmlHelper.DropDownListFor(expression, createSelectList(expression.ReturnType, selected));
    }

    /// <summary>
    /// Creates the select list.
    /// </summary>
    /// <param name="enumType">Type of the enum.</param>
    /// <param name="selectedItem">The selected item.</param>
    /// <returns></returns>
    private static IEnumerable<SelectListItem> createSelectList(Type enumType, string selectedItem)
    {
        return (from object item in Enum.GetValues(enumType)
                let fi = enumType.GetField(item.ToString())
                let attribute = fi.GetCustomAttributes(typeof (DescriptionAttribute), true).FirstOrDefault()
                let title = attribute == null ? item.ToString() : ((DescriptionAttribute) attribute).Description
                select new SelectListItem
                  {
                      Value = item.ToString(), 
                      Text = title, 
                      Selected = selectedItem == item.ToString()
                  }).ToList();
    }
}

2
แค่ความเห็นของฉัน แต่ฉันคิดว่าคำตอบนี้สะอาดกว่าคำตอบที่ยอมรับ ฉันชอบตัวเลือกในการใช้คุณลักษณะคำอธิบายเป็นพิเศษ ฉันเพิ่มรหัสเพื่อให้ผู้คนสามารถคัดลอก / วางได้โดยไม่ต้องดาวน์โหลด
Ben Mills

เรียกใช้เมธอดส่วนขยายเป็น EnumDropDownListFor แทนที่จะใช้ DropDownListFor: -> @ Html.EnumDropDownListFor (x => x.Gender)
sandeep Talabathula

สำหรับคนที่กำลังมองหาการเพิ่มองค์ประกอบอีกหนึ่ง "กรุณาเลือก" return htmlHelper.DropDownListFor (นิพจน์, createSelectList (expression.ReturnType, เลือก, firstElement), "Please Select");
Sandeep

1
ทำงานได้ดี! อย่างไรก็ตามในหน้ารายละเอียด DisplayFor () จะแสดงค่าที่เลือกของ enum แทนคำอธิบายที่เกี่ยวข้อง ฉันคิดว่าสิ่งนี้เรียกการโอเวอร์โหลดสำหรับ DisplayFor () สำหรับประเภท enum ใครมีวิธีแก้ปัญหานี้?
corix010

48

Html.DropDownListFor ต้องการเพียง IEnumerable เท่านั้นดังนั้นทางเลือกอื่นของโซลูชันของ Prise มีดังนี้ สิ่งนี้จะช่วยให้คุณเขียน:

@Html.DropDownListFor(m => m.SelectedItemType, Model.SelectedItemType.ToSelectList())

[ที่ SelectedItemType เป็นเขตข้อมูลในรูปแบบประเภท ItemTypes ของคุณและแบบจำลองของคุณไม่เป็นโมฆะ]

นอกจากนี้คุณไม่จำเป็นต้องทำให้วิธีการส่วนขยายเป็นมาตรฐานอย่างที่คุณสามารถใช้ enumValue.GetType () แทนที่จะเป็น typeof (T)

แก้ไข: วิธีการแก้ปัญหาแบบบูรณาการของไซมอนที่นี่เช่นกันและรวมถึงวิธีการขยาย ToDescription

public static class EnumExtensions
{
    public static IEnumerable<SelectListItem> ToSelectList(this Enum enumValue)
    {
        return from Enum e in Enum.GetValues(enumValue.GetType())
               select new SelectListItem
               {
                   Selected = e.Equals(enumValue),
                   Text = e.ToDescription(),
                   Value = e.ToString()
               };
    }

    public static string ToDescription(this Enum value)
    {
        var attributes = (DescriptionAttribute[])value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
        return attributes.Length > 0 ? attributes[0].Description : value.ToString();
    }
}

ไม่ทำงานสำหรับฉัน ('System.NullReferenceException: การอ้างอิงวัตถุไม่ได้ตั้งค่าเป็นอินสแตนซ์ของวัตถุ') ... 'รุ่น' ของฉันเป็นโมฆะ ... อาจมีบางสิ่งที่เกี่ยวข้องกับ 'GetNonNullableModelType' ซึ่ง Simon มี รวม
ผู้เรียน

@Cristi คุณมีสิทธิ์แก้ปัญหานี้ไม่ได้ตั้งใจที่จะใช้ในสภาพที่รุ่นของคุณเป็นโมฆะ ฉันพยายามหลีกเลี่ยงการออกแบบโดยทั่วไปและเริ่มต้นเป็นรุ่น "ว่าง" เมื่อเป็นกรณี
Zaid Masud

ฉันใหม่สำหรับ asp mvc แต่ฉันมีประสบการณ์ใน. NET ขอบคุณฉันจะตรวจสอบว่าคุณได้รับการแนะนำ Btw ส่วนขยาย ToDescription ของคุณอยู่ไกลเกินขอบเขต 'Enum' ฉันเดาว่าไปได้ดีสำหรับ 'วัตถุ' เอง นี่คือสิ่งที่ฉันใช้เมื่อฉันใช้รหัสของ Simon และทำความสะอาดมันอีกเล็กน้อย
ผู้เรียน

@ Cristi มันยากที่จะเข้าใจสิ่งที่คุณหมายถึงโดย "ไกลนอกขอบเขต 'Enum'" แต่ดูเหมือนว่าคุณกำลังบอกว่าวิธีการขยาย ToDescription ไม่ได้พิมพ์ลงใน ItemTypes enum อย่างรุนแรงหรือไม่ นี่คือเจตนาและทำให้วิธีการขยายโดยทั่วไปสามารถใช้งานได้โดย enums ทั้งหมด หากคุณกำลังเปรียบเทียบกับวิธีส่วนขยายทั่วไปจะมีข้อดีข้อเสียของแต่ละวิธี โดยเฉพาะอย่างยิ่งถ้าคุณกำเนิดคุณไม่สามารถทำให้มันถูก จำกัด บน enums เพียงอย่างเดียว
Zaid Masud

1
ยอดเยี่ยมด้วยความขอบคุณ ฉันเปลี่ยนค่า ToString เพื่อใช้ส่วนขยาย FromCamelCase ในกรณีที่ไม่มีคำอธิบาย นั่นคือวิธีม้วนผม :)
Valamas

33

ดังนั้นหากไม่มีฟังก์ชั่นเสริมหากคุณกำลังมองหาที่ง่ายและสะดวก .. นี่คือสิ่งที่ฉันทำ

<%= Html.DropDownListFor(x => x.CurrentAddress.State, new SelectList(Enum.GetValues(typeof(XXXXX.Sites.YYYY.Models.State))))%>

โดยที่ XXXXX.Sites.YYYY.Models.State เป็น enum

น่าจะดีกว่าถ้าทำฟังก์ชั่นตัวช่วย แต่เมื่อเวลาสั้น ๆ จะทำให้งานเสร็จ


สิ่งนี้ใช้ได้ผลกับการดรอปดาวน์ แต่คุณจะตั้งค่าเริ่มต้นที่เลือกไว้ในไวยากรณ์มีดโกนสำหรับ Html.DropDownListFor ได้อย่างไร ฉันต้องการแสดงตารางพร้อมกล่องคำสั่งผสมของ enums และฉันจำเป็นต้องตั้งค่าที่เลือกเช่นกันตามที่เคยเป็นมา
Johncl

2
ควรจะสามารถส่งผ่านพารามิเตอร์ตัวที่สองด้วยค่าที่เลือกไปยังฟังก์ชัน SelectList (IEnumerable, object) ใหม่ เอกสาร MSDN: msdn.microsoft.com/en-us/library/dd460123.aspx
Marty Trenouth

23

การขยายคำตอบของรางวัลและรูนหากคุณต้องการให้แอททริบิวต์ค่าของรายการไอเท็มที่คุณเลือกจับคู่กับค่าจำนวนเต็มของประเภทการแจงนับแทนค่าสตริงให้ใช้รหัสต่อไปนี้:

public static SelectList ToSelectList<T, TU>(T enumObj) 
    where T : struct
    where TU : struct
{
    if(!typeof(T).IsEnum) throw new ArgumentException("Enum is required.", "enumObj");

    var values = from T e in Enum.GetValues(typeof(T))
                 select new { 
                    Value = (TU)Convert.ChangeType(e, typeof(TU)),
                    Text = e.ToString() 
                 };

    return new SelectList(values, "Value", "Text", enumObj);
}

แทนที่จะจัดการกับค่าการแจงนับแต่ละอย่างเป็นวัตถุ TEnum เราสามารถถือมันเป็นวัตถุแล้วโยนมันเป็นจำนวนเต็มเพื่อรับค่า unboxed

หมายเหตุ: ฉันยังได้เพิ่มข้อ จำกัด ประเภททั่วไปเพื่อ จำกัด ประเภทที่ส่วนขยายนี้มีให้เฉพาะกับ structs (ประเภทพื้นฐานของ Enum) และการตรวจสอบความถูกต้องของชนิดรันไทม์ที่รับรองว่าโครงสร้างที่ส่งผ่านนั้นเป็น Enum

อัปเดต 10/23/12: เพิ่มพารามิเตอร์ประเภททั่วไปสำหรับประเภทพื้นฐานและปัญหาการไม่คอมไพล์ที่มีผลต่อการแก้ไข. NET 4+


ขอบคุณ! นี่คือคำตอบที่ฉันต้องการ ฉันกำลังจัดเก็บค่าจำนวนเต็มของ Enum เป็นคอลัมน์ในฐานข้อมูลและวิธีนี้ดูเหมือนว่าจะทำงานได้อย่างสมบูรณ์
grimus

แต่ถ้าคุณเก็บถ่านและไม่ใช่ int ล่ะ? ซึ่งเป็นกรณีของฉัน เห็นได้ชัดว่าฉันสามารถเปลี่ยน (int) เป็น (char) ได้ ทำอย่างไร
Stefanvds

@Stefandvds นี่เป็นคำถามที่ยอดเยี่ยมเกี่ยวกับการส่งไปยังประเภทตัวแทนที่ถูกต้อง จากการทดสอบที่ฉันทำมันดูเหมือนจะเป็นหนทางเดียวที่คุณจะสามารถบรรลุสิ่งนี้ได้โดยการระบุประเภทจริงเป็นพารามิเตอร์ประเภทอื่น ToSelectList<TEnum, TEnumValue>(this TEnum enumObj) { ... }
Nathan Taylor

@Stefandvds ดูคำถามนี้
Nathan Taylor

หากค่า enum ของคุณเป็น int Value = Convert.ToInt32(e)คุณก็สามารถใช้ (int)eไม่ได้รวบรวม :(
แอนดรูว์

11

เพื่อแก้ปัญหาการรับจำนวนแทนข้อความโดยใช้วิธีการขยายของ Prise

public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
{
  var values = from TEnum e in Enum.GetValues(typeof(TEnum))
               select new { ID = (int)Enum.Parse(typeof(TEnum),e.ToString())
                         , Name = e.ToString() };

  return new SelectList(values, "Id", "Name", enumObj);
}

นั่นคือสิ่งที่ฉันกำลังมองหาถึงแม้ว่ามันจะเป็น แต่น่าเกลียดกว่าที่ฉันคิดว่ามันจำเป็นต้องเป็น ผมสงสัยว่าทำไม Visual Studio จะไม่ให้คุณโยนโดยตรงเพื่อe int
แอนดรู

ID = Convert.ToInt32(e)หรือคุณก็สามารถใช้
แอนดรู

11

วิธีที่ง่ายที่สุดในการทำสิ่งนี้ให้สำเร็จ - โดยไม่มีสิ่งต่อพ่วงทั้งหมดที่ดูเหมือนว่า overkill คือ:

Enum ของคุณ:

    public enum SelectedLevel
    {
       Level1,
       Level2,
       Level3,
       Level4
    }

ภายในตัวควบคุมของคุณผูก Enum กับรายการ:

    List<SelectedLevel> myLevels = Enum.GetValues(typeof(SelectedLevel)).Cast<SelectedLevel>().ToList();

หลังจากนั้นให้โยนลงใน ViewBag:

    ViewBag.RequiredLevel = new SelectList(myLevels);

ในที่สุดก็ผูกมันไว้กับมุมมอง:

    @Html.DropDownList("selectedLevel", (SelectList)ViewBag.RequiredLevel, new { @class = "form-control" })

นี่เป็นวิธีที่ง่ายที่สุดที่ฉันพบและไม่ต้องการส่วนขยายใด ๆ หรือสิ่งที่บ้า

อัปเดต : ดูความคิดเห็นของแอนดรูด้านล่าง


3
ใช้งานได้เฉพาะเมื่อคุณไม่ได้กำหนดค่าใด ๆ ให้กับ enum ของคุณ หากคุณมีLevel1 = 1แล้วค่าแบบเลื่อนลงจะเป็นแทน"Level1" 1
แอนดรู

11

ทางออกที่ดีที่สุดที่ฉันพบคือการรวมบล็อกนี้กับคำตอบที่ไซมอน Goldstone ของ

สิ่งนี้อนุญาตให้ใช้ enum ในโมเดล แนวคิดหลักคือการใช้คุณสมบัติจำนวนเต็มเช่นเดียวกับ enum และเลียนแบบคุณสมบัติจำนวนเต็ม

จากนั้นใช้แอตทริบิวต์ [System.ComponentModel.Description] เพื่อใส่คำอธิบายประกอบโมเดลด้วยข้อความที่แสดงของคุณและใช้ส่วนขยาย "EnumDropDownListFor" ในมุมมองของคุณ

สิ่งนี้ทำให้ทั้งมุมมองและโมเดลอ่านได้ง่ายและบำรุงรักษาได้มาก

รุ่น:

public enum YesPartialNoEnum
{
    [Description("Yes")]
    Yes,
    [Description("Still undecided")]
    Partial,
    [Description("No")]
    No
}

//........

[Display(Name = "The label for my dropdown list")]
public virtual Nullable<YesPartialNoEnum> CuriousQuestion{ get; set; }
public virtual Nullable<int> CuriousQuestionId
{
    get { return (Nullable<int>)CuriousQuestion; }
    set { CuriousQuestion = (Nullable<YesPartialNoEnum>)value; }
}

ดู:

@using MyProject.Extensions
{
//...
    @Html.EnumDropDownListFor(model => model.CuriousQuestion)
//...
}

ส่วนขยาย (โดยตรงจากคำตอบของ Simon Goldstoneรวมอยู่ที่นี่เพื่อความครบถ้วน):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel;
using System.Reflection;
using System.Linq.Expressions;
using System.Web.Mvc.Html;

namespace MyProject.Extensions
{
    //Extension methods must be defined in a static class
    public static class MvcExtensions
    {
        private static Type GetNonNullableModelType(ModelMetadata modelMetadata)
        {
            Type realModelType = modelMetadata.ModelType;

            Type underlyingType = Nullable.GetUnderlyingType(realModelType);
            if (underlyingType != null)
            {
                realModelType = underlyingType;
            }
            return realModelType;
        }

        private static readonly SelectListItem[] SingleEmptyItem = new[] { new SelectListItem { Text = "", Value = "" } };

        public static string GetEnumDescription<TEnum>(TEnum value)
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());

            DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

            if ((attributes != null) && (attributes.Length > 0))
                return attributes[0].Description;
            else
                return value.ToString();
        }

        public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression)
        {
            return EnumDropDownListFor(htmlHelper, expression, null);
        }

        public static MvcHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, object htmlAttributes)
        {
            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);

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

สิ่งนี้ใช้ไม่ได้มีดโกน MVC 4 ในมุมมองหรือรันไทม์ error = "การโทรไม่ชัดเจนระหว่างวิธีการต่อไปนี้หรือคุณสมบัติ 'LDN.Extensions.MvcExtensions.EnumDropDownListFor <MyModel, LDN.Models.YesPartialNoEnum?> (System.Web.Mvc.HtmlHelper <MyModel>, ระบบ .Linq.Expressions.Expression <System.Func <MyModel, LDN.Models.YesPartialNoEnum? >>) 'และ .... "และวิธีการเดียวกันนี้กับอุปกรณ์เดิมซ้ำอีกครั้ง (ไม่อนุญาตให้ใช้ตัวอักษรมากพอที่นี่)
Marc


8
@Html.DropDownListFor(model => model.Type, Enum.GetNames(typeof(Rewards.Models.PropertyType)).Select(e => new SelectListItem { Text = e }))

ดี! วิธีรับค่าและข้อความจาก enum ด้วยวิธีนี้ ฉันหมายถึงฉันมี SomeEnum {some1 = 1, some2 = 2} ฉันต้องได้รับตัวเลข (1, 2) สำหรับค่าและข้อความ (some1, some2) สำหรับข้อความของรายการที่เลือก
Dmitresky

7

นี่คือคำตอบ Rune และรางวัลที่เปลี่ยนแปลงเพื่อใช้intค่าEnum เป็น ID

ตัวอย่าง Enum:

public enum ItemTypes
{
    Movie = 1,
    Game = 2,
    Book = 3
}

วิธีการขยาย:

    public static SelectList ToSelectList<TEnum>(this TEnum enumObj)
    {
        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                     select new { Id = (int)Enum.Parse(typeof(TEnum), e.ToString()), Name = e.ToString() };

        return new SelectList(values, "Id", "Name", (int)Enum.Parse(typeof(TEnum), enumObj.ToString()));
    }

ตัวอย่างการใช้งาน:

 <%=  Html.DropDownList("MyEnumList", ItemTypes.Game.ToSelectList()) %>

อย่าลืมอิมพอร์ตเนมสเปซที่มีเมธอด Extension

<%@ Import Namespace="MyNamespace.LocationOfExtensionMethod" %>

ตัวอย่างของ HTML ที่สร้าง:

<select id="MyEnumList" name="MyEnumList">
    <option value="1">Movie</option>
    <option selected="selected" value="2">Game</option>
    <option value="3">Book </option>
</select>

โปรดทราบว่ารายการที่คุณใช้โทรออกToSelectListเป็นรายการที่เลือก


Id = Convert.ToInt32(e)หรือคุณก็สามารถใช้
แอนดรู

6

นี่เป็นรุ่นสำหรับมีดโกน:

@{
    var itemTypesList = new List<SelectListItem>();
    itemTypesList.AddRange(Enum.GetValues(typeof(ItemTypes)).Cast<ItemTypes>().Select(
                (item, index) => new SelectListItem
                {
                    Text = item.ToString(),
                    Value = (index).ToString(),
                    Selected = Model.ItemTypeId == index
                }).ToList());
 }


@Html.DropDownList("ItemTypeId", itemTypesList)

สิ่งนี้จะใช้ได้ก็ต่อเมื่อค่า enum ของคุณประกอบด้วยค่าที่ต่อเนื่องกันเริ่มต้นด้วย 0 ค่าสถานะ enum จะไม่ทำงานกับสิ่งนี้ การใช้งานสร้างสรรค์ของ Selected ที่จัดทำดัชนีแล้ว
Suncat2000

6

ใน. NET Core คุณสามารถใช้สิ่งนี้:

@Html.DropDownListFor(x => x.Foo, Html.GetEnumSelectList<MyEnum>())

1
<select asp-for="Model.Foo" class="form-control" asp-items="@Html.GetEnumSelectList<MyEnum>()"></select>หรือผู้ช่วยแท็ก
Pascal R.

อ๋อ Id บอกว่าตัวช่วยแท็กดียิ่งขึ้นเนื่องจากรูปแบบใกล้เคียงกับ HTML ล้วนๆ);
GoldenAge

นอกจากนี้คุณสามารถทำเช่นนี้ @ Html.DropDownListFor (x => x.Foo, Html.GetEnumSelectList (typeof (FooEnum)))
Fereydoon Barikzehy

6

ตอนนี้ฟีเจอร์นี้รองรับการใช้งานนอกกรอบใน MVC 5.1 ผ่าน @Html.EnumDropDownListFor()

ตรวจสอบลิงค์ต่อไปนี้:

https://docs.microsoft.com/en-us/aspnet/mvc/overview/releases/mvc51-release-notes#Enum

เป็นเรื่องน่าอายจริง ๆ ที่ใช้เวลา 5 ปีของ Microsoft ในการดำเนินการเช่นคุณสมบัติซึ่งเป็นที่ต้องการตามการโหวตข้างต้น!


5

จากคำตอบของ Simon แนวทางที่คล้ายกันคือรับค่า Enum ที่จะแสดงจากไฟล์ทรัพยากรแทนที่จะเป็นแอตทริบิวต์คำอธิบายภายใน Enum เอง สิ่งนี้มีประโยชน์หากไซต์ของคุณต้องแสดงผลมากกว่าหนึ่งภาษาและหากคุณต้องมีไฟล์ทรัพยากรเฉพาะสำหรับ Enums คุณสามารถไปอีกขั้นหนึ่งและมีเพียงค่า Enum ใน Enum ของคุณและอ้างอิงจากส่วนขยายโดย การประชุมเช่น [EnumName] _ [EnumValue] - ในท้ายที่สุดการพิมพ์น้อยลง!

ส่วนขยายนั้นมีลักษณะดังนี้:

public static IHtmlString EnumDropDownListFor<TModel, TEnum>(this HtmlHelper<TModel> html, Expression<Func<TModel, TEnum>> expression)
{            
    var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);

    var enumType = Nullable.GetUnderlyingType(metadata.ModelType) ?? metadata.ModelType;

    var enumValues = Enum.GetValues(enumType).Cast<object>();

    var items = from enumValue in enumValues                        
                select new SelectListItem
                {
                    Text = GetResourceValueForEnumValue(enumValue),
                    Value = ((int)enumValue).ToString(),
                    Selected = enumValue.Equals(metadata.Model)
                };


    return html.DropDownListFor(expression, items, string.Empty, null);
}

private static string GetResourceValueForEnumValue<TEnum>(TEnum enumValue)
{
    var key = string.Format("{0}_{1}", enumValue.GetType().Name, enumValue);

    return Enums.ResourceManager.GetString(key) ?? enumValue.ToString();
}

ทรัพยากรในไฟล์ Enums.Resx ดูเหมือน ItemTypes_Movie: Film

อีกสิ่งหนึ่งที่ฉันต้องการทำคือแทนที่จะเรียกวิธีการขยายโดยตรงฉันควรจะเรียกมันด้วย @ Html.EditorFor (x => x.MyProperty) หรือนึกคิดว่ามีแบบฟอร์มทั้งหมดในแบบที่เป็นระเบียบ @ Html.EditorForModel () เมื่อต้องการทำสิ่งนี้ฉันเปลี่ยนเทมเพลตสตริงให้เป็นแบบนี้

@using MVCProject.Extensions

@{
    var type = Nullable.GetUnderlyingType(ViewData.ModelMetadata.ModelType) ?? ViewData.ModelMetadata.ModelType;

    @(typeof (Enum).IsAssignableFrom(type) ? Html.EnumDropDownListFor(x => x) : Html.TextBoxFor(x => x))
}

หากคุณสนใจสิ่งนี้ฉันได้รับคำตอบโดยละเอียดเพิ่มเติมที่นี่ในบล็อกของฉัน:

http://paulthecyclist.com/2013/05/24/enum-dropdown/


5

ฉันมาช้าไปงานปาร์ตี้ แต่สำหรับสิ่งที่คุ้มค่าฉันได้ blogged เกี่ยวกับเรื่องนี้มากโดยที่ฉันสร้างEnumHelperชั้นเรียนที่ช่วยให้การแปลงง่ายมาก

http://jnye.co/Posts/4/creating-a-dropdown-list-from-an-enum-in-mvc-and-c%23

ในตัวควบคุมของคุณ:

//If you don't have an enum value use the type
ViewBag.DropDownList = EnumHelper.SelectListFor<MyEnum>();

//If you do have an enum value use the value (the value will be marked as selected)    
ViewBag.DropDownList = EnumHelper.SelectListFor(MyEnum.MyEnumValue);

ในมุมมองของคุณ:

@Html.DropDownList("DropDownList")
@* OR *@
@Html.DropDownListFor(m => m.Property, ViewBag.DropDownList as SelectList, null)

ชั้นผู้ช่วย:

public static class EnumHelper
{
    // Get the value of the description attribute if the   
    // enum has one, otherwise use the value.  
    public static string GetDescription<TEnum>(this TEnum value)
    {
        var 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();
    }

    /// <summary>
    /// Build a select list for an enum
    /// </summary>
    public static SelectList SelectListFor<T>() where T : struct
    {
        Type t = typeof(T);
        return !t.IsEnum ? null
                         : new SelectList(BuildSelectListItems(t), "Value", "Text");
    }

    /// <summary>
    /// Build a select list for an enum with a particular value selected 
    /// </summary>
    public static SelectList SelectListFor<T>(T selected) where T : struct
    {
        Type t = typeof(T);
        return !t.IsEnum ? null
                         : new SelectList(BuildSelectListItems(t), "Text", "Value", selected.ToString());
    }

    private static IEnumerable<SelectListItem> BuildSelectListItems(Type t)
    {
        return Enum.GetValues(t)
                   .Cast<Enum>()
                   .Select(e => new SelectListItem { Value = e.ToString(), Text = e.GetDescription() });
    }
}

4

ฉันมาสายนี้มาก แต่ฉันเพิ่งพบวิธีที่ยอดเยี่ยมจริงๆในการทำเช่นนี้ด้วยโค้ดหนึ่งบรรทัดถ้าคุณยินดีที่จะเพิ่มUnconstrained Melodyแพ็คเกจ NuGet (ไลบรารีขนาดเล็กที่ดีจาก Jon Skeet)

วิธีนี้ดีกว่าเพราะ:

  1. ช่วยให้มั่นใจได้ (มีข้อ จำกัด ประเภททั่วไป) ว่าค่าเป็นค่า enum จริง ๆ (เนื่องจาก Melody ที่ไม่มีข้อ จำกัด )
  2. หลีกเลี่ยงการมวยที่ไม่จำเป็น (เนื่องจาก Melody ที่ไม่มีข้อ จำกัด )
  3. มันแคชคำอธิบายทั้งหมดเพื่อหลีกเลี่ยงการใช้การสะท้อนในทุกการโทร (เนื่องจาก Melody Unconstrained)
  4. มันเป็นรหัสน้อยกว่าโซลูชั่นอื่น ๆ !

ดังนั้นนี่คือขั้นตอนในการทำงานนี้:

  1. ในคอนโซลตัวจัดการแพคเกจ "ติดตั้งแพคเกจ UnconstrainedMelody"
  2. เพิ่มสถานที่ให้บริการในแบบจำลองของคุณเช่น:

    //Replace "YourEnum" with the type of your enum
    public IEnumerable<SelectListItem> AllItems
    {
        get
        {
            return Enums.GetValues<YourEnum>().Select(enumValue => new SelectListItem { Value = enumValue.ToString(), Text = enumValue.GetDescription() });
        }
    }

เมื่อคุณมีรายการ SelectListItem ที่เปิดเผยในแบบจำลองของคุณแล้วคุณสามารถใช้ @ Html.DropDownList หรือ @ Html.DropDownListFor โดยใช้คุณสมบัตินี้เป็นแหล่งที่มา


+1 สำหรับการใช้รหัสของ Jon Skeet :) แค่ล้อเล่นดี ๆ
Vamsi

3

วิธีแก้ไขส่วนขยายนี้อีกวิธีหนึ่ง - เวอร์ชันปัจจุบันไม่ได้เลือกค่าปัจจุบันของ enum ฉันแก้ไขบรรทัดสุดท้าย:

public static SelectList ToSelectList<TEnum>(this TEnum enumObj) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum) throw new ArgumentException("An Enumeration type is required.", "enumObj");

        var values = from TEnum e in Enum.GetValues(typeof(TEnum))
                       select new
                       {
                           ID = (int)Enum.Parse(typeof(TEnum), e.ToString()),
                           Name = e.ToString()
                       };


        return new SelectList(values, "ID", "Name", ((int)Enum.Parse(typeof(TEnum), enumObj.ToString())).ToString());
    }

3

หากคุณต้องการเพิ่มการรองรับการแปลเพียงแค่เปลี่ยนเมธอด s.toString () เป็นดังนี้:

ResourceManager rManager = new ResourceManager(typeof(Resources));
var dayTypes = from OperatorCalendarDay.OperatorDayType s in Enum.GetValues(typeof(OperatorCalendarDay.OperatorDayType))
               select new { ID = s, Name = rManager.GetString(s.ToString()) };

ในที่นี่ typeof (Resources) เป็นทรัพยากรที่คุณต้องการโหลดแล้วคุณจะได้รับสตริงที่แปลแล้วมีประโยชน์เช่นกันหากตัวแจงนับของคุณมีค่าที่มีหลายคำ


3

นี่คือวิธีใช้ตัวช่วยเวอร์ชันของฉัน ฉันใช้สิ่งนี้:

var values = from int e in Enum.GetValues(typeof(TEnum))
             select new { ID = e, Name = Enum.GetName(typeof(TEnum), e) };

แทนที่จะเป็น:

var values = from TEnum e in Enum.GetValues(typeof(TEnum))
           select new { ID = (int)Enum.Parse(typeof(TEnum),e.ToString())
                     , Name = e.ToString() };

นี่มันคือ:

public static SelectList ToSelectList<TEnum>(this TEnum self) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum)
        {
            throw new ArgumentException("self must be enum", "self");
        }

        Type t = typeof(TEnum);

        var values = from int e in Enum.GetValues(typeof(TEnum))
                     select new { ID = e, Name = Enum.GetName(typeof(TEnum), e) };

        return new SelectList(values, "ID", "Name", self);
    }

3

คุณยังสามารถใช้ HtmlHelpers ที่กำหนดเองของฉันใน Griffin.MvcContrib รหัสต่อไปนี้:

@Html2.CheckBoxesFor(model => model.InputType) <br />
@Html2.RadioButtonsFor(model => model.InputType) <br />
@Html2.DropdownFor(model => model.InputType) <br />

สร้าง:

ป้อนคำอธิบายรูปภาพที่นี่

https://github.com/jgauffin/griffin.mvccontrib


3

ฉันต้องการที่จะตอบคำถามนี้ในวิธีที่แตกต่างกันที่ผู้ใช้ไม่จำเป็นต้องทำอะไรในcontrollerหรือLinqแสดงออก ทางนี้...

ฉันมี ENUM

public enum AccessLevelEnum
    {
        /// <summary>
        /// The user cannot access
        /// </summary>
        [EnumMember, Description("No Access")]
        NoAccess = 0x0,

        /// <summary>
        /// The user can read the entire record in question
        /// </summary>
        [EnumMember, Description("Read Only")]
        ReadOnly = 0x01,

        /// <summary>
        /// The user can read or write
        /// </summary>
        [EnumMember, Description("Read / Modify")]
        ReadModify = 0x02,

        /// <summary>
        /// User can create new records, modify and read existing ones
        /// </summary>
        [EnumMember, Description("Create / Read / Modify")]
        CreateReadModify = 0x04,

        /// <summary>
        /// User can read, write, or delete
        /// </summary>
        [EnumMember, Description("Create / Read / Modify / Delete")]
        CreateReadModifyDelete = 0x08,

        /*/// <summary>
        /// User can read, write, or delete
        /// </summary>
        [EnumMember, Description("Create / Read / Modify / Delete / Verify / Edit Capture Value")]
        CreateReadModifyDeleteVerify = 0x16*/
    }

ตอนนี้ฉันก็ Canto สร้างโดยใช้นี้dropdownenum

@Html.DropDownList("accessLevel",new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum))),new { @class = "form-control" })

หรือ

@Html.DropDownListFor(m=>m.accessLevel,new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum))),new { @class = "form-control" })

หากคุณต้องการเลือกดัชนีให้ลองทำสิ่งนี้

@Html.DropDownListFor(m=>m.accessLevel,new SelectList(AccessLevelEnum.GetValues(typeof(AccessLevelEnum)) , AccessLevelEnum.NoAccess ),new { @class = "form-control" })

ที่นี่ฉันได้ใช้AccessLevelEnum.NoAccessเป็นพารามิเตอร์พิเศษสำหรับการเริ่มต้นเลือกแบบเลื่อนลง


3

ผมพบคำตอบที่นี่ อย่างไรก็ตาม enums ของฉันบางตัวมี[Description(...)]คุณสมบัติดังนั้นฉันจึงแก้ไขโค้ดเพื่อให้การสนับสนุนสำหรับสิ่งนั้น:

    enum Abc
    {
        [Description("Cba")]
        Abc,

        Def
    }


    public static MvcHtmlString EnumDropDownList<TEnum>(this HtmlHelper htmlHelper, string name, TEnum selectedValue)
    {
        IEnumerable<TEnum> values = Enum.GetValues(typeof(TEnum))
            .Cast<TEnum>();

        List<SelectListItem> items = new List<SelectListItem>();
        foreach (var value in values)
        {
            string text = value.ToString();

            var member = typeof(TEnum).GetMember(value.ToString());
            if (member.Count() > 0)
            {
                var customAttributes = member[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (customAttributes.Count() > 0)
                {
                    text = ((DescriptionAttribute)customAttributes[0]).Description;
                }
            }

            items.Add(new SelectListItem
            {
                Text = text,
                Value = value.ToString(),
                Selected = (value.Equals(selectedValue))
            });
        }

        return htmlHelper.DropDownList(
            name,
            items
            );
    }

หวังว่าจะช่วย


ฉันต้องการส่งคืนสมาชิกประเภท = DropdownList ฉันดีกับข้อความ = คำอธิบายคุณลักษณะ แต่พบว่ามันยากที่จะรับค่า int จาก Value
NanaFadanvis

2

@Simon Goldstone: ขอบคุณสำหรับการแก้ปัญหาของคุณมันสามารถนำไปใช้อย่างสมบูรณ์แบบในกรณีของฉัน ปัญหาเดียวคือฉันต้องแปลมันเป็น VB แต่ตอนนี้มันเสร็จแล้วและเพื่อประหยัดเวลาของคนอื่น (ในกรณีที่พวกเขาต้องการ) ฉันวางมันไว้ที่นี่:

Imports System.Runtime.CompilerServices
Imports System.ComponentModel
Imports System.Linq.Expressions

Public Module HtmlHelpers
    Private Function GetNonNullableModelType(modelMetadata As ModelMetadata) As Type
        Dim realModelType = modelMetadata.ModelType

        Dim underlyingType = Nullable.GetUnderlyingType(realModelType)

        If Not underlyingType Is Nothing Then
            realModelType = underlyingType
        End If

        Return realModelType
    End Function

    Private ReadOnly SingleEmptyItem() As SelectListItem = {New SelectListItem() With {.Text = "", .Value = ""}}

    Private Function GetEnumDescription(Of TEnum)(value As TEnum) As String
        Dim fi = value.GetType().GetField(value.ToString())

        Dim attributes = DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())

        If Not attributes Is Nothing AndAlso attributes.Length > 0 Then
            Return attributes(0).Description
        Else
            Return value.ToString()
        End If
    End Function

    <Extension()>
    Public Function EnumDropDownListFor(Of TModel, TEnum)(ByVal htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TEnum))) As MvcHtmlString
        Return EnumDropDownListFor(htmlHelper, expression, Nothing)
    End Function

    <Extension()>
    Public Function EnumDropDownListFor(Of TModel, TEnum)(ByVal htmlHelper As HtmlHelper(Of TModel), expression As Expression(Of Func(Of TModel, TEnum)), htmlAttributes As Object) As MvcHtmlString
        Dim metaData As ModelMetadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData)
        Dim enumType As Type = GetNonNullableModelType(metaData)
        Dim values As IEnumerable(Of TEnum) = [Enum].GetValues(enumType).Cast(Of TEnum)()

        Dim items As IEnumerable(Of SelectListItem) = From value In values
            Select New SelectListItem With
            {
                .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 Then
            items = SingleEmptyItem.Concat(items)
        End If

        Return htmlHelper.DropDownListFor(expression, items, htmlAttributes)
    End Function
End Module

จบคุณใช้มันแบบนี้:

@Html.EnumDropDownListFor(Function(model) (model.EnumField))

2

ฉันลงเอยด้วยการสร้างวิธีการขยายเพื่อทำสิ่งที่เป็นคำตอบการยอมรับที่นี่ ครึ่งสุดท้ายของสรุปสาระสำคัญกับ Enum โดยเฉพาะ

https://gist.github.com/3813767


2
@Html.DropdownListFor(model=model->Gender,new List<SelectListItem>
{
 new ListItem{Text="Male",Value="Male"},
 new ListItem{Text="Female",Value="Female"},
 new ListItem{Text="--- Select -----",Value="-----Select ----"}
}
)

2
@Html.DropDownListFor(model => model.MaritalStatus, new List<SelectListItem> 
{  

new SelectListItem { Text = "----Select----", Value = "-1" },


new SelectListItem { Text = "Marrid", Value = "M" },


 new SelectListItem { Text = "Single", Value = "S" }

})

ฉันคิดว่านี่ไม่ใช่คำตอบที่ถูกต้องมันไม่ได้ใช้ enum เลยเพื่อเติมลง
แอนดรู
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.