ASP.NET'te bir Enum'u bir DropDownList denetimine nasıl bağlarsınız?


126

Diyelim ki aşağıdaki basit numaralandırma var:

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

Bu numaralandırmayı bir DropDownList denetimine nasıl bağlayabilirim, böylece açıklamalar listede görüntülenir ve bir seçenek seçildikten sonra ilişkili sayısal değeri (1,2,3) alır?

Yanıtlar:


112

Muhtemelen verileri bir sıralama olduğu için bağlamazdım ve derleme süresinden sonra değişmez (bu durgun anlardan birine sahip olmadıkça ).

Sıralamayı yinelemek daha iyidir:

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

Veya C # 'da aynı

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
Bu cevap için çok teşekkürler. GetType (Response) benim için işe yaramadı çünkü Enum sınıfı yerine Enum örneğini aldım. Bu yüzden onun yerine enumInstance.GetType () kullanıyorum.
Sebastian

2
C # kullanmak benim için çalışmıyor, çünkü hem getValues ​​hem de getNames aynı, birinci benzer nesneler ve ikinci benzer dizge döndürüyor. Numaralamanın tanımı şu şekildedir: public enum eResult {Right = 1,
NoncontrolledError

9
Bu arada C # 'da, itemNames [i] indeksi ile Array'e erişemezsiniz, bunu sadece arrayObject.GetValue (i) ile yapabilirsiniz ve bu şekilde, her iki durumda da sadece adı döndürür.
Javiere


5
Bunun neden bu kadar çok olumlu oyu var? Kod (en az c #) artık çalışıyor ve sözdizimi hataları içeriyor.
Dave

69

Bir NumaralandırmadanEnumeration bir IDictionary<int,string>(Enum değeri ve ad çifti) almak için aşağıdaki yardımcı program sınıfını kullanın ; daha sonra kimlik sözlüğünü bağlanabilir bir Denetime bağlarsınız .

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

Örnek: Numaralandırma verilerini bir denetime bağlamak için yardımcı program sınıfını kullanma

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

1
+1. Ben kullandım, ancak anahtar ve değerin yanlış olduğunu düşünüyorum. Bu bir IDictionary <string, int> döndürmelidir
Colin

Bunun tüm enum türlerinde (uint, ulong, long, vb. Gibi) doğru davranmayacağına dikkat edilmelidir. Normalde aranacak en etkili alan anahtardır. Bu durumda, tamsayılar basit bir <, =,> karşılaştırması ve her karakter için bir dizenin <ve> karşılaştırması olduğu için bu int olacaktır.
Trisped

43

Bunu ASP.NET MVC için kullanıyorum :

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

36

Benim versiyonum sadece yukarıdakilerin sıkıştırılmış bir şeklidir:

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

4
olmalıdır (Enum.GetValues'da int r (typeof (Response))) yoksa açıklamayı ad ve değer olarak bağlar ...
Evan

2
ListItem değerine numaralandırma üyesinin adını eklediği için bu çalışmaz. İnt türüne dönüştürmek çoğu durumda işe yarar, ancak enum bir uint, ulong veya long ise işe yaramaz.
53'te Trisped

IMHO çok daha iyi bir çözüm.
Vippy

23
public enum Color
{
    RED,
    GREEN,
    BLUE
}

Her Enum türü System.Enum'dan türetilir. Verileri bir açılır liste denetimine bağlamaya (ve değeri almaya) yardımcı olan iki statik yöntem vardır. Bunlar Enum.GetNames ve Enum.Parse. GetNames'i kullanarak, açılır liste kontrolünüze aşağıdaki gibi bağlanabilirsiniz:

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

Şimdi Enum değerini Seçime Geri Dönmek istiyorsanız ...

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

2
iyi cevap ama küçük bir ipucu: Color selectedColor = (Color) Enum.Parse (typeof (Color), ddColor.SelectedValue);
sma6871

11

Tüm gönderileri okuduktan sonra, açılır listede enum açıklamasını göstermenin yanı sıra Düzenleme modunda görüntülenirken açılır menüden Model'den uygun değeri seçmeyi desteklemek için kapsamlı bir çözüm buldum:

Sıralama:

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

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

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

enum uzantı sınıfı:

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

Model sınıfı:

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

ve Görüntüle:

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

ve bu açılır listeyi Model'e bağlamadan kullanıyorsanız, bunun yerine şunu kullanabilirsiniz:

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

Böylece, açılır listenizin enum değerleri yerine Açıklama görüntülemesini bekleyebilirsiniz. Ayrıca Düzenle söz konusu olduğunda, modeliniz sayfa gönderildikten sonra açılır listeden seçilen değer ile güncellenecektir.


1
Harika, özellikle [Description] ek açıklamalarının olduğu kısım. Bu tekniği benimseyeceğim.
Baxter

Düzgün ve Temiz Açıklama. Kudos Amir !!

8

Diğerlerinin daha önce de söylediği gibi - duruma bağlı olarak farklı numaralandırmalara bağlamanız gerekmedikçe bir numaralandırmaya bağlanmayın. Bunu yapmanın birkaç yolu vardır, aşağıda birkaç örnek.

ObjectDataSource

Bunu ObjectDataSource ile yapmanın bildirime dayalı bir yolu. İlk olarak, DropDownList'i şunlara bağlamak için List'i döndürecek bir BusinessObject sınıfı oluşturun:

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

Ardından, bu BO sınıfını işaret etmek için ASPX sayfasına biraz HTML işaretlemesi ekleyin:

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

Bu seçenek, arkasında kod gerektirmez.

DataBind Arkasındaki Kod

HTML'yi ASPX sayfasındaki en aza indirmek ve Code Behind'da bağlama yapmak için:

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

Her neyse, işin püf noktası GetValues, GetNames vb. Enum türü yöntemlerinin sizin için çalışmasını sağlamaktır.


6

Bunu ASP.NET'te nasıl yapacağımdan emin değilim ama bu gönderiye bakın ... yardımcı olabilir mi?

Enum.GetValues(typeof(Response));

6

Linq kullanabilirsiniz:

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

Altıncı Cevabı Kullanan Genel Kod.

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

Bu cevabı bulduktan sonra bunu yapmanın daha iyi (en azından daha zarif) bir yolu olduğunu düşündüğüm bir şey buldum, geri gelip burada paylaşacağımı düşündüm.

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

Bu muhtemelen eski bir sorudur .. ama benimkini böyle yaptım.

Model:

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
}

Ardından Görünümde: açılır menüyü nasıl kullanacağınız aşağıda açıklanmıştır.

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

Bu, sıralama listenizdeki her şeyi doldurmalıdır. Bu yardımcı olur umarım..


Ancak bu işe yarar, dize değişmezlerini boşluklarla birleştirmek istiyorsanız bir uzantı sınıfına ihtiyacınız vardır.

1
Bu en iyi cevap. @Nikul, bir uzatma sınıfına ihtiyacınız yok. Yalnızca ek açıklamaları kullanmanız gerekir. [Display(Name = "Option number one")] Option1,
rooter


1

Her listeyi geçebilmek için neden böyle kullanmıyorsunuz?


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();
        }
Ve kullanımı şu kadar basit:

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


1

ASP.NET o zamandan beri bazı daha fazla işlevsellikle güncellendi ve artık açılır listeye yerleşik enum kullanabilirsiniz.

Enum'un kendisine bağlanmak istiyorsanız, şunu kullanın:

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

Bir Response örneğine bağlıyorsanız, şunu kullanın:

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

0

Bu, LINQ kullanarak Açılır Menüye Enum ve DataBind (Metin ve Değer) Siparişi Verme çözümümdür

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

Birleşik giriş kutunuzda (veya başka bir kontrolde) daha kullanıcı dostu bir açıklama olmasını isterseniz, aşağıdaki işlevle Açıklama özniteliğini kullanabilirsiniz:

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

Burada, Açıklama özniteliklerinin uygulandığı bir enum örneği verilmiştir:

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

Sonra kontrole böyle bağlayın ...

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

Bu şekilde, değişken adı gibi görünmek zorunda kalmadan açılır menüye istediğiniz metni koyabilirsiniz.


0

Uzantı yöntemlerini de kullanabilirsiniz. Uzantılara aşina olmayanlar için VB ve C # belgelerine bakmanızı öneririm .


VB Uzantısı:

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

Uzantıyı kullanmak için:

Imports <projectName>.CustomExtensions.ListItemCollectionExtension

...

yourDropDownList.Items.AddEnum(Of EnumType)()

C # Uzantısı:

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

Uzantıyı kullanmak için:

using CustomExtensions.ListItemCollectionExtension;

...

yourDropDownList.Items.AddEnum<EnumType>()

Seçili öğeyi aynı anda ayarlamak istiyorsanız

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

ile

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)

İnt boyutu yerine System.Enum'a dönüştürülerek ve çıktı sorunları önlenir. Örneğin 0xFFFF0000, uint olarak 4294901760, ancak int olarak -65536 olur.

TryCast ve System.Enum olarak Convert.ChangeType'tan (enumTypeValues ​​[i], enumUnderType) .ToString () (hız testlerimde 12:13) biraz daha hızlı.



0

Kabul edilen çözüm işe yaramaz, ancak aşağıdaki kod diğerlerinin en kısa çözümü aramasına yardımcı olacaktır.

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

0

Bunu çok daha kısa sürede yapabilirsin

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);
            }
        }
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.