คุณผูก Enum กับตัวควบคุม DropDownList ใน ASP.NET ได้อย่างไร


126

สมมติว่าฉันมี enum ง่ายๆดังต่อไปนี้:

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

ฉันจะผูก enum นี้กับตัวควบคุม DropDownList เพื่อให้คำอธิบายแสดงในรายการรวมทั้งดึงค่าตัวเลขที่เกี่ยวข้อง (1,2,3) ได้อย่างไรเมื่อมีการเลือกตัวเลือก

คำตอบ:


112

ฉันอาจจะไม่ผูกข้อมูลตามที่มันเป็น enum และมันจะไม่เปลี่ยนแปลงหลังจากที่รวบรวมเวลา (ถ้าฉันมีหนึ่งในบรรดาโง่ช่วงเวลา)

ดีกว่าที่จะวนซ้ำผ่าน 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

หรือเหมือนกันใน 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
ขอบคุณมากสำหรับคำตอบนี้ GetType (การตอบกลับ) ใช้ไม่ได้สำหรับฉันเพราะฉันได้รับอินสแตนซ์ของ Enum แทนที่จะเป็นคลาส Enum ดังนั้นฉันจึงใช้ enumInstance.GetType () แทน
Sebastian

2
การใช้ C # มันไม่ได้ผลสำหรับฉันเพราะทั้ง getValues ​​และ getNames ส่งคืนเหมือนกันวัตถุที่คล้ายกันตัวแรกและสตริงที่สองเหมือนกัน คำจำกัดความของ enum เป็นดังนี้ public enum eResult {Right = 1, NoncontrolledError = 2,}
Javiere

9
ใน C # คุณไม่สามารถเข้าถึง Array ด้วย index itemNames [i] คุณสามารถทำได้ด้วย arrayObject.GetValue (i) เท่านั้นและด้วยวิธีนี้มันจะส่งคืนชื่อในทั้งสองกรณี
Javiere

1
ฉันแก้ไขโดยผสมโซลูชันนี้กับสิ่งนี้stackoverflow.com/questions/3213432/…
Javiere

5
เหตุใดจึงมีการโหวตเพิ่มขึ้นมากมาย ตอนนี้โค้ด (อย่างน้อย c #) ทำงานและมีข้อผิดพลาดทางไวยากรณ์
Dave

69

ใช้คลาสยูทิลิตี้ต่อไปนี้Enumerationเพื่อรับIDictionary<int,string>(Enum value & name pair) จากEnumeration ; จากนั้นคุณผูกIDictionaryกับการควบคุมแบบผูกได้

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

ตัวอย่าง:การใช้คลาสยูทิลิตี้เพื่อผูกข้อมูลการแจงนับกับตัวควบคุม

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

1
+1 ฉันเคยใช้มาแล้ว แต่ฉันคิดว่าคีย์และค่านั้นผิดทาง สิ่งนี้ควรส่งคืน IDictionary <string, int>
Colin

ควรสังเกตว่าสิ่งนี้จะทำงานไม่ถูกต้องกับ enum ทุกประเภท (เช่น uint, ulong, long ฯลฯ ) โดยปกติช่องที่มีประสิทธิภาพที่สุดในการค้นหาคือกุญแจสำคัญ ในกรณีนี้สิ่งนั้นจะเป็น int เนื่องจากจำนวนเต็มเป็นการเปรียบเทียบ <, =,> อย่างง่ายกับการเปรียบเทียบ <และ> ของสตริงสำหรับแต่ละอักขระ
Trisped

43

ฉันใช้สิ่งนี้สำหรับ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

เวอร์ชันของฉันเป็นเพียงรูปแบบการบีบอัดข้างต้น:

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

4
ควรเป็น (int r ใน Enum.GetValues ​​(typeof (Response))) หรือจะผูกคำอธิบายเป็นชื่อและค่า ...
Evan

2
ไม่ได้ผลเนื่องจากแทรกชื่อของสมาชิกการแจงนับในค่าของ ListItem การแปลงเป็น int จะได้ผลในกรณีส่วนใหญ่ แต่ไม่ใช่ถ้า enum เป็น uint, ulong หรือ long
Trisped

ทางออกที่ดีกว่ามาก IMHO
Vippy

23
public enum Color
{
    RED,
    GREEN,
    BLUE
}

Enum ทุกประเภทมาจาก System.Enum มีวิธีการแบบคงที่สองวิธีที่ช่วยผูกข้อมูลกับตัวควบคุมรายการดรอปดาวน์ (และดึงค่า) นี่คือ Enum.GetNames และ Enum.Parse เมื่อใช้ GetNames คุณสามารถเชื่อมโยงกับตัวควบคุมรายการดรอปดาวน์ของคุณได้ดังนี้:

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

ตอนนี้ถ้าคุณต้องการให้ค่า Enum กลับมาที่การเลือก ....

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

2
คำตอบที่ดี แต่มีเคล็ดลับเล็กน้อย: Color selectedColor = (Color) Enum.Parse (typeof (Color), ddColor.SelectedValue);
sma6871

11

หลังจากอ่านโพสต์ทั้งหมดฉันได้พบกับโซลูชันที่ครอบคลุมเพื่อรองรับการแสดงคำอธิบาย enum ในรายการแบบเลื่อนลงรวมถึงการเลือกค่าที่เหมาะสมจาก Model ในเมนูแบบเลื่อนลงเมื่อแสดงในโหมดแก้ไข:

enum:

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

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

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

คลาสส่วนขยาย 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))
                          });
    }
}

คลาสรุ่น:

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

และดู:

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

และหากคุณใช้ดรอปดาวน์โดยไม่ผูกมัดกับโมเดลคุณสามารถใช้สิ่งนี้แทนได้:

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

ดังนั้นคุณสามารถคาดหวังว่าดรอปดาวน์ของคุณจะแสดงคำอธิบายแทนค่า enum นอกจากนี้เมื่อพูดถึง Edit โมเดลของคุณจะได้รับการอัปเดตตามค่าที่เลือกแบบเลื่อนลงหลังจากโพสต์หน้า


1
ทำได้ดีมากโดยเฉพาะบิตที่มีคำอธิบายประกอบ [Description] ฉันจะนำเทคนิคนี้ไปใช้
Baxter

คำอธิบายที่เรียบร้อยและสะอาด รุ่งโรจน์อาเมียร์ !!

8

อย่างที่คนอื่นพูดไปแล้ว - อย่าใช้ฐานข้อมูลกับ enum เว้นแต่คุณจะต้องผูกกับ enums ที่แตกต่างกันขึ้นอยู่กับสถานการณ์ มีหลายวิธีในการดำเนินการดังตัวอย่างด้านล่างนี้

ObjectDataSource

วิธีที่เปิดเผยในการดำเนินการกับ ObjectDataSource ขั้นแรกสร้างคลาส BusinessObject ที่จะส่งคืนรายการเพื่อผูก DropDownList กับ:

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

จากนั้นเพิ่มมาร์กอัป HTML ลงในเพจ ASPX เพื่อชี้ไปที่คลาส BO นี้:

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

ตัวเลือกนี้ไม่จำเป็นต้องใช้รหัสหลัง

รหัสหลัง DataBind

ในการย่อ HTML ในเพจ ASPX ให้เล็กที่สุดและผูกใน Code Behind:

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

อย่างไรก็ตามเคล็ดลับคือให้วิธีการประเภท Enum ของ GetValues, GetNames และอื่น ๆ ทำงานให้คุณ


6

ฉันไม่แน่ใจว่าจะทำอย่างไรใน ASP.NET แต่ลองดูโพสต์นี้ ... มันอาจช่วยได้?

Enum.GetValues(typeof(Response));

6

คุณสามารถใช้ 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);
}


3

รหัสทั่วไปใช้คำตอบที่หก

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

หลังจากพบคำตอบนี้ฉันได้สิ่งที่ฉันคิดว่าเป็นวิธีที่ดีกว่า (อย่างน้อยก็สง่างามกว่า) ในการทำเช่นนี้ฉันคิดว่าฉันจะกลับมาแบ่งปันที่นี่

Page_Load:

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

LoadValues:

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

SaveValues:

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

2

นี่อาจจะเป็นคำถามเก่า .. แต่นี่คือวิธีที่ฉันทำของฉัน

รุ่น:

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
}

จากนั้นในมุมมอง: นี่คือวิธีใช้เติมข้อมูลในเมนูแบบเลื่อนลง

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

สิ่งนี้ควรเติมข้อมูลทุกอย่างในรายการ enum ของคุณ หวังว่านี่จะช่วย ..


อย่างไรก็ตามวิธีนี้ใช้ได้ผลคุณต้องมีคลาสส่วนขยายหากคุณต้องการรวมตัวอักษรสตริงเข้ากับช่องว่าง

1
นี่คือคำตอบที่ดีที่สุด @ นิกูลคุณไม่จำเป็นต้องมีคลาสเสริม คุณต้องใช้คำอธิบายประกอบเท่านั้น [Display(Name = "Option number one")] Option1,
rooter


1

ทำไมไม่ใช้แบบนี้เพื่อให้สามารถส่งผ่านทุกรายการได้


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();
        }
และการใช้งานนั้นง่ายเพียงแค่:

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


1

ASP.NET ได้รับการอัปเดตด้วยฟังก์ชันเพิ่มเติมบางอย่างและตอนนี้คุณสามารถใช้ enum ในตัวเพื่อดร็อปดาวน์ได้

หากคุณต้องการผูกกับ Enum เองให้ใช้สิ่งนี้:

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

หากคุณผูกพันกับอินสแตนซ์ของการตอบกลับให้ใช้สิ่งนี้:

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

0

นี่คือวิธีแก้ปัญหาของฉันสำหรับ Order an Enum และ DataBind (Text and Value) ไปยัง Dropdown โดยใช้ 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

หากคุณต้องการมีคำอธิบายที่เป็นมิตรกับผู้ใช้มากขึ้นในกล่องคำสั่งผสมของคุณ (หรือการควบคุมอื่น ๆ ) คุณสามารถใช้แอตทริบิวต์คำอธิบายกับฟังก์ชันต่อไปนี้:

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

นี่คือตัวอย่างของ enum ที่ใช้แอตทริบิวต์ Description:

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

จากนั้นผูกควบคุมเช่นนั้น ...

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

วิธีนี้คุณสามารถใส่ข้อความที่ต้องการลงในเมนูแบบเลื่อนลงโดยไม่ต้องมีลักษณะเหมือนชื่อตัวแปร


0

คุณยังสามารถใช้วิธีการขยาย สำหรับผู้ที่ไม่คุ้นเคยกับนามสกุลผมขอแนะนำให้ตรวจสอบVBและC #เอกสาร


ส่วนขยาย 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

ในการใช้ส่วนขยาย:

Imports <projectName>.CustomExtensions.ListItemCollectionExtension

...

yourDropDownList.Items.AddEnum(Of EnumType)()

ส่วนขยาย 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")));
            }
        }
    }
}

ในการใช้ส่วนขยาย:

using CustomExtensions.ListItemCollectionExtension;

...

yourDropDownList.Items.AddEnum<EnumType>()

หากคุณต้องการตั้งค่ารายการที่เลือกในเวลาเดียวกันให้แทนที่

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

กับ

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)

โดยการแปลงเป็น System.Enum แทนที่จะหลีกเลี่ยงปัญหาขนาด int และเอาต์พุต ตัวอย่างเช่น 0xFFFF0000 จะเป็น 4294901760 เป็น uint แต่จะเป็น -65536 เป็น int

TryCast และเป็น System.Enum เร็วกว่า Convert.ChangeType เล็กน้อย (enumTypeValues ​​[i], enumUnderType) .oString () (12:13 ในการทดสอบความเร็วของฉัน)



0

โซลูชันที่ยอมรับใช้ไม่ได้ผล แต่โค้ดด้านล่างจะช่วยให้ผู้อื่นมองหาวิธีแก้ปัญหาที่สั้นที่สุด

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

0

คุณสามารถทำได้สั้นกว่านี้มาก

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);
            }
        }
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.