Làm thế nào để bạn liên kết Enum với điều khiển DropDownList trong ASP.NET?


126

Hãy nói rằng tôi có enum đơn giản sau đây:

enum Response
{
    Yes = 1,
    No = 2,
    Maybe = 3
}

Làm cách nào tôi có thể liên kết enum này với điều khiển DropDownList để các mô tả được hiển thị trong danh sách cũng như truy xuất giá trị số liên quan (1,2,3) sau khi tùy chọn đã được chọn?

Câu trả lời:


112

Tôi có lẽ sẽ không ràng buộc dữ liệu vì nó là một enum, và nó sẽ không thay đổi sau thời gian biên dịch (trừ khi tôi đang gặp một trong những Stoopid khoảnh khắc).

Tốt hơn chỉ nên lặp qua enum:

Dim itemValues As Array = System.Enum.GetValues(GetType(Response))
Dim itemNames As Array = System.Enum.GetNames(GetType(Response))

For i As Integer = 0 To itemNames.Length - 1
    Dim item As New ListItem(itemNames(i), itemValues(i))
    dropdownlist.Items.Add(item)
Next

Hoặc tương tự trong C #

Array itemValues = System.Enum.GetValues(typeof(Response));
Array itemNames = System.Enum.GetNames(typeof(Response));

for (int i = 0; i <= itemNames.Length - 1 ; i++) {
    ListItem item = new ListItem(itemNames[i], itemValues[i]);
    dropdownlist.Items.Add(item);
}

1
Cảm ơn rất nhiều cho câu trả lời này. GetType (Phản hồi) không hoạt động với tôi vì tôi nhận được một thể hiện của Enum, thay vì lớp Enum. Vì vậy, tôi sử dụng enumInstance.GetType () để thay thế.
Sebastian

2
Sử dụng C #, nó không hoạt động đối với tôi, bởi vì cả getValues ​​và getNames đều trả về như nhau, thứ nhất giống như các đối tượng và chuỗi thứ hai như chuỗi. Định nghĩa của enum là như thế này: public enum eResult {Right = 1, NoncontrolledError = 2,}
Javiere

9
Nhân tiện, trong C #, bạn không thể truy cập vào Array với chỉ mục itemNames [i], bạn chỉ có thể làm điều đó với ArrayObject.GetValue (i) và theo cách đó, nó chỉ trả lại tên trong cả hai trường hợp.
Javiere

1
Tôi đã giải quyết nó bằng cách trộn giải pháp này với một stackoverflow.com/questions/3213432/iêu
Javiere

5
Tại sao điều này có rất nhiều upvote. Mã (ít nhất là c #) hiện hoạt động và có lỗi cú pháp.
Dave

69

Sử dụng lớp tiện ích sau Enumerationđể nhận IDictionary<int,string>(cặp giá trị & tên) từ bảng liệt kê ; sau đó bạn liên kết IDadata với một điều khiển ràng buộc .

public static class Enumeration
{
    public static IDictionary<int, string> GetAll<TEnum>() where TEnum: struct
    {
        var enumerationType = typeof (TEnum);

        if (!enumerationType.IsEnum)
            throw new ArgumentException("Enumeration type is expected.");

        var dictionary = new Dictionary<int, string>();

        foreach (int value in Enum.GetValues(enumerationType))
        {
            var name = Enum.GetName(enumerationType, value);
            dictionary.Add(value, name);
        }

        return dictionary;
    }
}

Ví dụ: Sử dụng lớp tiện ích để liên kết dữ liệu liệt kê với điều khiển

ddlResponse.DataSource = Enumeration.GetAll<Response>();
ddlResponse.DataTextField = "Value";
ddlResponse.DataValueField = "Key";
ddlResponse.DataBind();

1
+1. Tôi đã sử dụng nó, nhưng tôi nghĩ rằng chìa khóa và giá trị là sai cách. Điều này sẽ trả về một IDadata <chuỗi, int>
Colin

Cần lưu ý rằng điều này sẽ không hoạt động chính xác của tất cả các loại enum (như uint, ulong, dài, v.v.) Thông thường lĩnh vực hiệu quả nhất để tìm kiếm là chìa khóa. Trong trường hợp này, đó sẽ là int vì các số nguyên là một so sánh <, =,> đơn giản so với so sánh <và> của một chuỗi cho mỗi char.
Trisped

43

Tôi sử dụng cái này cho ASP.NET MVC :

Html.DropDownListFor(o => o.EnumProperty, Enum.GetValues(typeof(enumtype)).Cast<enumtype>().Select(x => new SelectListItem { Text = x.ToString(), Value = ((int)x).ToString() }))

36

Phiên bản của tôi chỉ là một dạng nén ở trên:

foreach (Response r in Enum.GetValues(typeof(Response)))
{
    ListItem item = new ListItem(Enum.GetName(typeof(Response), r), r.ToString());
    DropDownList1.Items.Add(item);
}

4
nên là (int r trong Enum.GetValues ​​(typeof (Phản hồi))) hoặc nó sẽ chỉ ràng buộc mô tả như tên và giá trị ...
Evan

2
điều này không hoạt động, vì nó chèn tên của thành viên liệt kê vào giá trị của ListItem. Chuyển đổi sang int sẽ hoạt động trong hầu hết các trường hợp, nhưng không phải nếu enum là uint, ulong hoặc dài.
Trisped

Giải pháp tốt hơn nhiều IMHO.
Vippy

23
public enum Color
{
    RED,
    GREEN,
    BLUE
}

Mọi loại Enum đều xuất phát từ System.Enum. Có hai phương thức tĩnh giúp liên kết dữ liệu với điều khiển danh sách thả xuống (và truy xuất giá trị). Đây là Enum.GetNames và Enum.Pude. Sử dụng GetNames, bạn có thể liên kết với điều khiển danh sách thả xuống của mình như sau:

protected System.Web.UI.WebControls.DropDownList ddColor;

private void Page_Load(object sender, System.EventArgs e)
{
     if(!IsPostBack)
     {
        ddColor.DataSource = Enum.GetNames(typeof(Color));
        ddColor.DataBind();
     }
}

Bây giờ nếu bạn muốn giá trị Enum Quay lại Lựa chọn ....

  private void ddColor_SelectedIndexChanged(object sender, System.EventArgs e)
  {
    Color selectedColor = (Color)Enum.Parse(typeof(Color),ddColor.SelectedValue
  }

2
câu trả lời hay nhưng một mẹo nhỏ: Màu được chọnColor = (Color) Enum.Pude (typeof (Color), ddColor.SelectedValue);
sma6871

11

Sau khi đọc tất cả các bài viết, tôi đã đưa ra một giải pháp toàn diện để hỗ trợ hiển thị mô tả enum trong danh sách thả xuống cũng như chọn giá trị phù hợp từ Model trong danh sách thả xuống khi hiển thị trong chế độ Chỉnh sửa:

enum:

using System.ComponentModel;
public enum CompanyType
{
    [Description("")]
    Null = 1,

    [Description("Supplier")]
    Supplier = 2,

    [Description("Customer")]
    Customer = 3
}

lớp mở rộng enum:

using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.Mvc;

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

    public static IEnumerable<SelectListItem> ToSelectList<T>(this System.Enum enumValue)
    {
        return
            System.Enum.GetValues(enumValue.GetType()).Cast<T>()
                  .Select(
                      x =>
                      new SelectListItem
                          {
                              Text = ((System.Enum)(object) x).ToDescription(),
                              Value = x.ToString(),
                              Selected = (enumValue.Equals(x))
                          });
    }
}

Lớp mẫu:

public class Company
{
    public string CompanyName { get; set; }
    public CompanyType Type { get; set; }
}

và xem:

@Html.DropDownListFor(m => m.Type,
@Model.Type.ToSelectList<CompanyType>())

và nếu bạn đang sử dụng danh sách thả xuống đó mà không ràng buộc với Model, bạn có thể sử dụng thay thế này:

@Html.DropDownList("type",                  
Enum.GetValues(typeof(CompanyType)).Cast<CompanyType>()
.Select(x => new SelectListItem {Text = x.ToDescription(), Value = x.ToString()}))

Vì vậy, bằng cách làm như vậy, bạn có thể mong đợi trình đơn thả xuống của mình hiển thị Mô tả thay vì giá trị enum. Ngoài ra, khi nói đến Chỉnh sửa, mô hình của bạn sẽ được cập nhật theo giá trị được chọn thả xuống sau khi đăng trang.


1
Hoàn thành tốt, đặc biệt là bit với các chú thích [Mô tả]. Tôi sẽ áp dụng kỹ thuật này.
Baxter

Giải thích gọn gàng và sạch sẽ. Kudos Amir !!

8

Như những người khác đã nói - không tham gia vào một enum, trừ khi bạn cần liên kết với các enum khác nhau tùy theo tình huống. Có một số cách để làm điều này, một vài ví dụ dưới đây.

ObjectDataSource

Một cách khai báo với ObjectDataSource. Đầu tiên, tạo một lớp BusinessObject sẽ trả về Danh sách để liên kết DropDownList với:

public class DropDownData
{
    enum Responses { Yes = 1, No = 2, Maybe = 3 }

    public String Text { get; set; }
    public int Value { get; set; }

    public List<DropDownData> GetList()
    {
        var items = new List<DropDownData>();
        foreach (int value in Enum.GetValues(typeof(Responses)))
        {
            items.Add(new DropDownData
                          {
                              Text = Enum.GetName(typeof (Responses), value),
                              Value = value
                          });
        }
        return items;
    }
}

Sau đó thêm một số đánh dấu HTML vào trang ASPX để trỏ đến lớp BO này:

<asp:DropDownList ID="DropDownList1" runat="server" 
    DataSourceID="ObjectDataSource1" DataTextField="Text" DataValueField="Value">
</asp:DropDownList>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" 
    SelectMethod="GetList" TypeName="DropDownData"></asp:ObjectDataSource>

Tùy chọn này không yêu cầu mã phía sau.

Mã đằng sau DataBind

Để giảm thiểu HTML trong trang ASPX và liên kết trong Code đằng sau:

enum Responses { Yes = 1, No = 2, Maybe = 3 }

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        foreach (int value in Enum.GetValues(typeof(Responses)))
        {
            DropDownList1.Items.Add(new ListItem(Enum.GetName(typeof(Responses), value), value.ToString()));
        }
    }
}

Dù sao, mẹo là để các phương thức loại Enum của GetValues, GetNames, v.v. làm việc cho bạn.


6

Tôi không chắc chắn làm thế nào để làm điều đó trong ASP.NET nhưng kiểm tra bài đăng này ... nó có thể giúp gì?

Enum.GetValues(typeof(Response));

6

Bạn có thể sử dụng linq:

var responseTypes= Enum.GetNames(typeof(Response)).Select(x => new { text = x, value = (int)Enum.Parse(typeof(Response), x) });
    DropDownList.DataSource = responseTypes;
    DropDownList.DataTextField = "text";
    DropDownList.DataValueField = "value";
    DropDownList.DataBind();

5
Array itemValues = Enum.GetValues(typeof(TaskStatus));
Array itemNames = Enum.GetNames(typeof(TaskStatus));

for (int i = 0; i <= itemNames.Length; i++)
{
    ListItem item = new ListItem(itemNames.GetValue(i).ToString(),
    itemValues.GetValue(i).ToString());
    ddlStatus.Items.Add(item);
}

4
public enum Color
{
    RED,
    GREEN,
    BLUE
}

ddColor.DataSource = Enum.GetNames(typeof(Color));
ddColor.DataBind();

3

Mã chung sử dụng câu trả lời sáu.

public static void BindControlToEnum(DataBoundControl ControlToBind, Type type)
{
    //ListControl

    if (type == null)
        throw new ArgumentNullException("type");
    else if (ControlToBind==null )
        throw new ArgumentNullException("ControlToBind");
    if (!type.IsEnum)
        throw new ArgumentException("Only enumeration type is expected.");

    Dictionary<int, string> pairs = new Dictionary<int, string>();

    foreach (int i in Enum.GetValues(type))
    {
        pairs.Add(i, Enum.GetName(type, i));
    }
    ControlToBind.DataSource = pairs;
    ListControl lstControl = ControlToBind as ListControl;
    if (lstControl != null)
    {
        lstControl.DataTextField = "Value";
        lstControl.DataValueField = "Key";
    }
    ControlToBind.DataBind();

}

3

Sau khi tìm thấy câu trả lời này, tôi đã nghĩ ra cách mà tôi nghĩ là cách tốt hơn (ít nhất là thanh lịch hơn), tôi nghĩ tôi sẽ quay lại và chia sẻ nó ở đây.

Trang_Load:

DropDownList1.DataSource = Enum.GetValues(typeof(Response));
DropDownList1.DataBind();

LoadValues:

Response rIn = Response.Maybe;
DropDownList1.Text = rIn.ToString();

Lưu trữ giá trị:

Response rOut = (Response) Enum.Parse(typeof(Response), DropDownList1.Text);

2

Đây có lẽ là một câu hỏi cũ .. nhưng đây là cách tôi đã làm của tôi.

Mô hình:

public class YourEntity
{
   public int ID { get; set; }
   public string Name{ get; set; }
   public string Description { get; set; }
   public OptionType Types { get; set; }
}

public enum OptionType
{
    Unknown,
    Option1, 
    Option2,
    Option3
}

Sau đó, trong Chế độ xem: đây là cách sử dụng danh sách thả xuống.

@Html.EnumDropDownListFor(model => model.Types, htmlAttributes: new { @class = "form-control" })

Điều này sẽ điền mọi thứ trong danh sách enum của bạn. Hi vọng điêu nay co ich..


Tuy nhiên, điều này hoạt động, bạn cần một lớp mở rộng nếu bạn muốn kết hợp chuỗi ký tự chuỗi với khoảng trắng.

1
Đây là câu trả lời tốt nhất. @Nikul, bạn không cần một lớp mở rộng. Bạn chỉ cần sử dụng chú thích. [Display(Name = "Option number one")] Option1,
bẻ khóa


1

Tại sao không sử dụng như thế này để có thể vượt qua mọi listControle:


public static void BindToEnum(Type enumType, ListControl lc)
        {
            // get the names from the enumeration
            string[] names = Enum.GetNames(enumType);
            // get the values from the enumeration
            Array values = Enum.GetValues(enumType);
            // turn it into a hash table
            Hashtable ht = new Hashtable();
            for (int i = 0; i < names.Length; i++)
                // note the cast to integer here is important
                // otherwise we'll just get the enum string back again
                ht.Add(names[i], (int)values.GetValue(i));
            // return the dictionary to be bound to
            lc.DataSource = ht;
            lc.DataTextField = "Key";
            lc.DataValueField = "Value";
            lc.DataBind();
        }
Và việc sử dụng chỉ đơn giản như:

BindToEnum(typeof(NewsType), DropDownList1);
BindToEnum(typeof(NewsType), CheckBoxList1);
BindToEnum(typeof(NewsType), RadoBuuttonList1);


1

ASP.NET đã được cập nhật với một số chức năng khác và bây giờ bạn có thể sử dụng enum tích hợp để thả xuống.

Nếu bạn muốn liên kết với chính Enum, hãy sử dụng:

@Html.DropDownList("response", EnumHelper.GetSelectList(typeof(Response)))

Nếu bạn đang ràng buộc vào một trường hợp Phản hồi, hãy sử dụng:

// Assuming Model.Response is an instance of Response
@Html.EnumDropDownListFor(m => m.Response)

0

Đây là giải pháp của tôi để Đặt hàng Enum và DataBind (Văn bản và Giá trị) cho thả xuống bằng LINQ

var mylist = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().ToList<MyEnum>().OrderBy(l => l.ToString());
foreach (MyEnum item in mylist)
    ddlDivisao.Items.Add(new ListItem(item.ToString(), ((int)item).ToString()));


0

Nếu bạn muốn có một mô tả thân thiện hơn với người dùng trong hộp tổ hợp của mình (hoặc điều khiển khác), bạn có thể sử dụng thuộc tính Mô tả với chức năng sau:

    public static object GetEnumDescriptions(Type enumType)
    {
        var list = new List<KeyValuePair<Enum, string>>();
        foreach (Enum value in Enum.GetValues(enumType))
        {
            string description = value.ToString();
            FieldInfo fieldInfo = value.GetType().GetField(description);
            var attribute = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false).First();
            if (attribute != null)
            {
                description = (attribute as DescriptionAttribute).Description;
            }
            list.Add(new KeyValuePair<Enum, string>(value, description));
        }
        return list;
    }

Dưới đây là một ví dụ về enum với các thuộc tính Mô tả được áp dụng:

    enum SampleEnum
    {
        NormalNoSpaces,
        [Description("Description With Spaces")]
        DescriptionWithSpaces,
        [Description("50%")]
        Percent_50,
    }

Sau đó, Bind để kiểm soát như vậy ...

        m_Combo_Sample.DataSource = GetEnumDescriptions(typeof(SampleEnum));
        m_Combo_Sample.DisplayMember = "Value";
        m_Combo_Sample.ValueMember = "Key";

Bằng cách này bạn có thể đặt bất kỳ văn bản nào bạn muốn vào trình đơn thả xuống mà không cần phải trông giống như một tên biến


0

Bạn cũng có thể sử dụng các phương thức mở rộng. Đối với những người không quen thuộc với các tiện ích mở rộng, tôi khuyên bạn nên kiểm tra tài liệu VBC # .


Mở rộng VB:

Namespace CustomExtensions
    Public Module ListItemCollectionExtension

        <Runtime.CompilerServices.Extension()> _
        Public Sub AddEnum(Of TEnum As Structure)(items As System.Web.UI.WebControls.ListItemCollection)
            Dim enumerationType As System.Type = GetType(TEnum)
            Dim enumUnderType As System.Type = System.Enum.GetUnderlyingType(enumType)

            If Not enumerationType.IsEnum Then Throw New ArgumentException("Enumeration type is expected.")

            Dim enumTypeNames() As String = System.Enum.GetNames(enumerationType)
            Dim enumTypeValues() As TEnum = System.Enum.GetValues(enumerationType)

            For i = 0 To enumTypeNames.Length - 1
                items.Add(New System.Web.UI.WebControls.ListItem(saveResponseTypeNames(i), TryCast(enumTypeValues(i), System.Enum).ToString("d")))
            Next
        End Sub
    End Module
End Namespace

Để sử dụng tiện ích mở rộng:

Imports <projectName>.CustomExtensions.ListItemCollectionExtension

...

yourDropDownList.Items.AddEnum(Of EnumType)()

Gia hạn C #:

namespace CustomExtensions
{
    public static class ListItemCollectionExtension
    {
        public static void AddEnum<TEnum>(this System.Web.UI.WebControls.ListItemCollection items) where TEnum : struct
        {
            System.Type enumType = typeof(TEnum);
            System.Type enumUnderType = System.Enum.GetUnderlyingType(enumType);

            if (!enumType.IsEnum) throw new Exception("Enumeration type is expected.");

            string[] enumTypeNames = System.Enum.GetNames(enumType);
            TEnum[] enumTypeValues = (TEnum[])System.Enum.GetValues(enumType);

            for (int i = 0; i < enumTypeValues.Length; i++)
            {
                items.add(new System.Web.UI.WebControls.ListItem(enumTypeNames[i], (enumTypeValues[i] as System.Enum).ToString("d")));
            }
        }
    }
}

Để sử dụng tiện ích mở rộng:

using CustomExtensions.ListItemCollectionExtension;

...

yourDropDownList.Items.AddEnum<EnumType>()

Nếu bạn muốn đặt mục đã chọn đồng thời thay thế

items.Add(New System.Web.UI.WebControls.ListItem(saveResponseTypeNames(i), saveResponseTypeValues(i).ToString("d")))

với

Dim newListItem As System.Web.UI.WebControls.ListItem
newListItem = New System.Web.UI.WebControls.ListItem(enumTypeNames(i), Convert.ChangeType(enumTypeValues(i), enumUnderType).ToString())
newListItem.Selected = If(EqualityComparer(Of TEnum).Default.Equals(selected, saveResponseTypeValues(i)), True, False)
items.Add(newListItem)

Bằng cách chuyển đổi sang System.Enum, sau đó tránh các vấn đề về kích thước và đầu ra int. Ví dụ: 0xFFFF0000 sẽ là 4294901760 dưới dạng uint nhưng sẽ là -65536 dưới dạng int.

TryCast và như System.Enum nhanh hơn một chút so với Convert.ChangeType (enumTypeValues ​​[i], enumUnderType) .ToString () (12:13 trong các bài kiểm tra tốc độ của tôi).



0

Giải pháp được chấp nhận không hoạt động, nhưng mã dưới đây sẽ giúp những người khác tìm kiếm giải pháp ngắn nhất.

 foreach (string value in Enum.GetNames(typeof(Response)))
                    ddlResponse.Items.Add(new ListItem()
                    {
                        Text = value,
                        Value = ((int)Enum.Parse(typeof(Response), value)).ToString()
                    });

0

Bạn có thể làm điều này ngắn hơn rất nhiều

public enum Test
    {
        Test1 = 1,
        Test2 = 2,
        Test3 = 3
    }
    class Program
    {
        static void Main(string[] args)
        {

            var items = Enum.GetValues(typeof(Test));

            foreach (var item in items)
            {
                //Gives you the names
                Console.WriteLine(item);
            }


            foreach(var item in (Test[])items)
            {
                // Gives you the numbers
                Console.WriteLine((int)item);
            }
        }
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.