Mengikat enum ke kotak kombo WinForms, dan kemudian menyetelnya


122

banyak orang telah menjawab pertanyaan tentang bagaimana mengikat enum ke kotak kombo di WinForms. Seperti ini:

comboBox1.DataSource = Enum.GetValues(typeof(MyEnum));

Tapi itu sangat tidak berguna tanpa bisa mengatur nilai sebenarnya untuk ditampilkan.

Saya telah mencoba:

comboBox1.SelectedItem = MyEnum.Something; // Does not work. SelectedItem remains null

Saya juga telah mencoba:

comboBox1.SelectedIndex = Convert.ToInt32(MyEnum.Something); // ArgumentOutOfRangeException, SelectedIndex remains -1

Apakah ada yang punya ide bagaimana melakukan ini?


2
Mengapa tidak mencoba ComboBox.SelectedValue saja?
Oliver Friedrich

5
Jika pertanyaan Anda telah dijawab, Anda benar-benar harus memilih jawaban.
Ryan The Leach

Titik penyatuan data enum tidak begitu jelas. Enum kemungkinan tidak akan berubah selama runtime. Anda juga bisa menulis metode ekstensi yang akan mengisi koleksi item kotak kombo dengan semua nilai enum.
Andreas


@OliverFriedrich SelectedValuemenyebabkan InvalidOperationExceptionsaya. "Tidak dapat mengatur SelectedValuedalam ListControldengan kosong ValueMember."
Tyler

Jawaban:


161

Enum

public enum Status { Active = 0, Canceled = 3 }; 

Mengatur nilai drop-down darinya

cbStatus.DataSource = Enum.GetValues(typeof(Status));

Mendapatkan enum dari item yang dipilih

Status status; 
Enum.TryParse<Status>(cbStatus.SelectedValue.ToString(), out status); 

5
Terima kasih, ini berhasil untuk saya. Ingatlah bahwa tryparse adalah pernyataan .net 4.0.
real_yggdrasil

Bagi saya SelectedValue selalu nol. Tampaknya kotak kombo tidak diinisialisasi. (myEnum) this.GridView.CurrentRow.Cells ["comboColumnCell"]. Nilai. Saya bisa melihat nilainya tetapi secara internal itu melempar pengecualian pointer nol
ssal

3
Inilah cara yang OP tidak ingin gunakan. Masalahnya adalah bahwa nama pengguna ditampilkan dalam kode dari setiap nilai, yang sering kali direfaktor dan tidak ramah pengguna.
Alejandro

5
Mengapa menggunakan TryParse daripada Parse? ... var status (Status) Enum.Parse (typeof (Status), cbStatus.SelectedValue.ToString ()); ... Anda mengikat enum ke kotak kombo sehingga Anda TAHU bahwa nilainya harus berupa nilai enum yang valid dan jika bukan berarti ada sesuatu yang tidak beres dan Anda mungkin menginginkan pengecualian.
bytedev

1
Mengapa ini dipilih untuk dilupakan? Pertanyaannya adalah bagaimana mengatur secara terprogram nilai yang dipilih dari kotak kombo, menggunakan salah satu nilai enum.
Tyler

39

Untuk menyederhanakan:

Pertama Inisialisasi perintah ini: (mis. Setelah InitalizeComponent())

yourComboBox.DataSource =  Enum.GetValues(typeof(YourEnum));

Untuk mengambil item yang dipilih di combobox:

YourEnum enum = (YourEnum) yourComboBox.SelectedItem;

Jika Anda ingin menyetel nilai untuk kotak kombo:

yourComboBox.SelectedItem = YourEnem.Foo;

2
Ini berfungsi selama nilai Tampilan sama dengan anggota Nilai, jika tidak, tidak.
Lord of Scripts

15

Kode

comboBox1.SelectedItem = MyEnum.Something;

ok, masalahnya harus ada di DataBinding. Penugasan DataBinding terjadi setelah konstruktor, terutama saat combobox pertama kali ditampilkan. Cobalah untuk mengatur nilai pada event Load. Misalnya, tambahkan kode ini:

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    comboBox1.SelectedItem = MyEnum.Something;
}

Dan periksa apakah itu berhasil.


12

Mencoba:

comboBox1.SelectedItem = MyEnum.Something;

EDIT:

Ups, Anda sudah mencobanya. Namun, itu berhasil untuk saya ketika comboBox saya disetel menjadi DropDownList.

Berikut adalah kode lengkap saya yang berfungsi untuk saya (dengan DropDown dan DropDownList):

public partial class Form1 : Form
{
    public enum BlahEnum
    { 
        Red,
        Green,
        Blue,
        Purple
    }

    public Form1()
    {
        InitializeComponent();

        comboBox1.DataSource = Enum.GetValues(typeof(BlahEnum));

    }

    private void button1_Click(object sender, EventArgs e)
    {
        comboBox1.SelectedItem = BlahEnum.Blue;
    }
}

menarik, sangat bagus Anda dapat melakukan `comboBox1.SelectedItem = BlahEnum.Blue;` tapi bagaimana jika Anda ingin benda-benda di kotak kombo menjadi string misalnya item kotak kombo menjadi "pil vitamin kunyah".?
barlop

11

Katakanlah Anda memiliki enum berikut

public enum Numbers {Zero = 0, One, Two};

Anda perlu memiliki struct untuk memetakan nilai-nilai tersebut ke string:

public struct EntityName
{
    public Numbers _num;
    public string _caption;

    public EntityName(Numbers type, string caption)
    {
        _num = type;
        _caption = caption;
    }

    public Numbers GetNumber() 
    {
        return _num;
    }

    public override string ToString()
    {
        return _caption;
    }
}

Sekarang kembalikan array objek dengan semua enum yang dipetakan ke string:

public object[] GetNumberNameRange()
{
    return new object[]
    {
        new EntityName(Number.Zero, "Zero is chosen"),
        new EntityName(Number.One, "One is chosen"),
        new EntityName(Number.Two, "Two is chosen")
    };
}

Dan gunakan yang berikut ini untuk mengisi kotak kombo Anda:

ComboBox numberCB = new ComboBox();
numberCB.Items.AddRange(GetNumberNameRange());

Buat fungsi untuk mengambil jenis enum kalau-kalau Anda ingin meneruskannya ke suatu fungsi

public Numbers GetConversionType() 
{
    EntityName type = (EntityName)numberComboBox.SelectedItem;
    return type.GetNumber();           
}

dan kemudian kamu akan baik-baik saja :)


+1 solusi yang bagus. Baru-baru ini mengalami masalah ini dan diselesaikan dengan cara yang sama (hanya dengan a Tuplesebagai gantinya). Saya akan mengubah nilai enum dan deskripsinya menjadi properti, lalu menambahkan numberCB.DisplayProperty = "Caption"; `dan numberCB.ValueProperty = "Num"agar Anda dapat menggunakan SelectedValuedan mengikatnya secara langsung.
Alejandro

IMHO, mungkin contoh source code lebih lengkap, jika juga ada fungsi seperti Add “All” / “Select All” pilihan ke ComboBox yang digunakan untuk memfilter semua baris dalam pencarian.
Kiquenet

5

Coba ini:

// fill list
MyEnumDropDownList.DataSource = Enum.GetValues(typeof(MyEnum));

// binding
MyEnumDropDownList.DataBindings.Add(new Binding("SelectedValue", StoreObject, "StoreObjectMyEnumField"));

StoreObject adalah contoh objek saya dengan properti StoreObjectMyEnumField untuk menyimpan nilai MyEnum.


1
Ini adalah pendekatan terbaik sejauh ini, tetapi sejauh ini, itu tidak berhasil untuk saya. Saya harus menggunakan "SelectedItem" daripada "SelectedValue"
Tiago Freitas Leal

4
 public static void FillByEnumOrderByNumber<TEnum>(this System.Windows.Forms.ListControl ctrl, TEnum enum1, bool showValueInDisplay = true) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum) throw new ArgumentException("An Enumeration type is required.", "enumObj");

        var values = from TEnum enumValue in Enum.GetValues(typeof(TEnum))
                     select
                        new
                         KeyValuePair<TEnum, string>(   (enumValue), enumValue.ToString());

        ctrl.DataSource = values
            .OrderBy(x => x.Key)

            .ToList();

        ctrl.DisplayMember = "Value";
        ctrl.ValueMember = "Key";

        ctrl.SelectedValue = enum1;
    }
    public static void  FillByEnumOrderByName<TEnum>(this System.Windows.Forms.ListControl ctrl, TEnum enum1, bool showValueInDisplay = true  ) where TEnum : struct
    {
        if (!typeof(TEnum).IsEnum) throw new ArgumentException("An Enumeration type is required.", "enumObj");

        var values = from TEnum enumValue in Enum.GetValues(typeof(TEnum))
                     select 
                        new 
                         KeyValuePair<TEnum,string> ( (enumValue),  enumValue.ToString()  );

        ctrl.DataSource = values
            .OrderBy(x=>x.Value)
            .ToList();

        ctrl.DisplayMember = "Value";
        ctrl.ValueMember = "Key";

        ctrl.SelectedValue = enum1;
    }

maksud kamu apa ? Saya tidak mengerti komentar Anda. metode ekstensi ini berfungsi
Mickey Perlstein

Itu tergantung pada apakah nomor enum Anda mengizinkan ATAU FLag. jika demikian Anda bisa menambahkan sebuah bendera yang 255 disebut Semua, dan memanggil fungsi dengan Semua sebagai enum1, yang membuat default. yaitu comboBox1.FillByEnumOrderByName (MyEnum.All)
Mickey Perlstein

Opsi apa pun seperti ini: var l = values.OrderBy (x => x.Value) .ToList (); l. Sisipkan (0, "Semua");
Kiquenet

enum saya adalah enum A {duck = 0, swan = 1, joker = 3}; sistem Anda tidak akan berfungsi untuk situasi saya.
Mickey Perlstein

3

Ini adalah solusi untuk memuat item enum di combobox:

comboBox1.Items.AddRange( Enum.GetNames(typeof(Border3DStyle)));

Dan kemudian gunakan item enum sebagai teks:

toolStripStatusLabel1.BorderStyle = (Border3DStyle)Enum.Parse(typeof(Border3DStyle),comboBox1.Text);

3

Berdasarkan jawaban dari @Amir Shenouda, saya berakhir dengan ini:

Definisi Enum:

public enum Status { Active = 0, Canceled = 3 }; 

Mengatur nilai drop down darinya:

cbStatus.DataSource = Enum.GetValues(typeof(Status));

Mendapatkan enum dari item yang dipilih:

Status? status = cbStatus.SelectedValue as Status?;

2
mengapa menggunakan nullable? Anda dapat menggunakan casting eksplisit (casting tanda kurung) dan tidak menggunakan nullable
John Demetriou

2
public Form1()
{
    InitializeComponent();
    comboBox.DataSource = EnumWithName<SearchType>.ParseEnum();
    comboBox.DisplayMember = "Name";
}

public class EnumWithName<T>
{
    public string Name { get; set; }
    public T Value { get; set; }

    public static EnumWithName<T>[] ParseEnum()
    {
        List<EnumWithName<T>> list = new List<EnumWithName<T>>();

        foreach (object o in Enum.GetValues(typeof(T)))
        {
            list.Add(new EnumWithName<T>
            {
                Name = Enum.GetName(typeof(T), o).Replace('_', ' '),
                Value = (T)o
            });
        }

        return list.ToArray();
    }
}

public enum SearchType
{
    Value_1,
    Value_2
}

IMHO, mungkin lebih lengkap contoh source code-nya, kalau juga ada fungsi seperti Add “All” / “Select All” ke ComboBox yang digunakan untuk menyaring semua baris dalam pencarian.
Kiquenet


1

Saya menggunakan metode helper berikut, yang dapat Anda ikat ke daftar Anda.

    ''' <summary>
    ''' Returns enumeration as a sortable list.
    ''' </summary>
    ''' <param name="t">GetType(some enumeration)</param>
    Public Shared Function GetEnumAsList(ByVal t As Type) As SortedList(Of String, Integer)

        If Not t.IsEnum Then
            Throw New ArgumentException("Type is not an enumeration.")
        End If

        Dim items As New SortedList(Of String, Integer)
        Dim enumValues As Integer() = [Enum].GetValues(t)
        Dim enumNames As String() = [Enum].GetNames(t)

        For i As Integer = 0 To enumValues.GetUpperBound(0)
            items.Add(enumNames(i), enumValues(i))
        Next

        Return items

    End Function

1

Ubah enum menjadi daftar string dan tambahkan ini ke comboBox

comboBox1.DataSource = Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>();

Setel nilai yang ditampilkan menggunakan selectedItem

comboBox1.SelectedItem = SomeEnum.SomeValue;

1

Tak satu pun dari ini berhasil untuk saya, tetapi ini berhasil (dan memiliki manfaat tambahan karena dapat memiliki deskripsi yang lebih baik untuk nama setiap enum). Saya tidak yakin apakah itu karena pembaruan .net atau bukan, tetapi terlepas dari itu, saya pikir ini adalah cara terbaik. Anda perlu menambahkan referensi ke:

menggunakan System.ComponentModel;

enum MyEnum
{
    [Description("Red Color")]
    Red = 10,
    [Description("Blue Color")]
    Blue = 50
}

....

    private void LoadCombobox()
    {
        cmbxNewBox.DataSource = Enum.GetValues(typeof(MyEnum))
            .Cast<Enum>()
            .Select(value => new
            {
                (Attribute.GetCustomAttribute(value.GetType().GetField(value.ToString()), typeof(DescriptionAttribute)) as DescriptionAttribute).Description,
                value
            })
            .OrderBy(item => item.value)
            .ToList();
        cmbxNewBox.DisplayMember = "Description";
        cmbxNewBox.ValueMember = "value";
    }

Kemudian ketika Anda ingin mengakses data gunakan dua baris ini:

        Enum.TryParse<MyEnum>(cmbxNewBox.SelectedValue.ToString(), out MyEnum proc);
        int nValue = (int)proc;

1

Ini mungkin tidak akan pernah terlihat di antara semua tanggapan lainnya, tetapi ini adalah kode yang saya buat, ini memiliki manfaat menggunakan DescriptionAttribute jika ada, tetapi sebaliknya menggunakan nama nilai enum itu sendiri.

Saya menggunakan kamus karena memiliki pola item kunci / nilai yang sudah jadi. SEBUAHList<KeyValuePair<string,object>> juga akan berfungsi dan tanpa hashing yang tidak perlu, tetapi kamus membuat kode yang lebih bersih.

Saya mendapatkan anggota yang memiliki MemberTypedari Fielddan yang literal. Ini membuat urutan hanya anggota yang merupakan nilai enum. Ini kuat karena enum tidak dapat memiliki bidang lain.

public static class ControlExtensions
{
    public static void BindToEnum<TEnum>(this ComboBox comboBox)
    {
        var enumType = typeof(TEnum);

        var fields = enumType.GetMembers()
                              .OfType<FieldInfo>()
                              .Where(p => p.MemberType == MemberTypes.Field)
                              .Where(p => p.IsLiteral)
                              .ToList();

        var valuesByName = new Dictionary<string, object>();

        foreach (var field in fields)
        {
            var descriptionAttribute = field.GetCustomAttribute(typeof(DescriptionAttribute), false) as DescriptionAttribute;

            var value = (int)field.GetValue(null);
            var description = string.Empty;

            if (!string.IsNullOrEmpty(descriptionAttribute?.Description))
            {
                description = descriptionAttribute.Description;
            }
            else
            {
                description = field.Name;
            }

            valuesByName[description] = value;
        }

        comboBox.DataSource = valuesByName.ToList();
        comboBox.DisplayMember = "Key";
        comboBox.ValueMember = "Value";
    }


}

0
comboBox1.SelectedItem = MyEnum.Something;

seharusnya bekerja dengan baik ... Bagaimana Anda bisa tahu bahwa SelectedItemitu nol?


Saya bisa memeriksanya di debugger. Saya berasumsi itu karena tipe SelectedItem adalah objek, yaitu tipe referensi, dan enum adalah tipe nilai. Meskipun saya mengharapkan kompiler untuk menangkapnya.

0

Anda dapat menggunakan fungsi "FindString ..":

Public Class Form1
    Public Enum Test
        pete
        jack
        fran
        bill
    End Enum
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ComboBox1.DataSource = [Enum].GetValues(GetType(Test))
        ComboBox1.SelectedIndex = ComboBox1.FindStringExact("jack")
        ComboBox1.SelectedIndex = ComboBox1.FindStringExact(Test.jack.ToString())
        ComboBox1.SelectedIndex = ComboBox1.FindStringExact([Enum].GetName(GetType(Test), Test.jack))
        ComboBox1.SelectedItem = Test.bill
    End Sub
End Class

0

Anda dapat menggunakan daftar nilai KeyValuePair sebagai sumber data untuk kotak kombo. Anda akan membutuhkan metode pembantu di mana Anda dapat menentukan jenis enum dan mengembalikan IEnumerable> di mana int adalah nilai enum dan string adalah nama dari nilai enum. Dalam kotak kombo Anda, setel properti DisplayMember ke 'Key' dan properti ValueMember ke 'Value'. Value dan Key adalah properti publik dari struktur KeyValuePair. Kemudian saat Anda menyetel properti SelectedItem ke nilai enum seperti yang Anda lakukan, properti itu akan berfungsi.


0

Saat ini saya menggunakan properti Item daripada DataSource, itu berarti saya harus memanggil Add untuk setiap nilai enum, tetapi ini adalah enum kecil, dan kode sementara tetap.

Kemudian saya bisa melakukan Convert.ToInt32 pada nilai dan mengaturnya dengan SelectedIndex.

Solusi sementara, tapi YAGNI untuk saat ini.

Bersorak untuk idenya, saya mungkin akan menggunakannya ketika saya melakukan versi yang tepat setelah mendapatkan umpan balik pelanggan.



0
comboBox1.DataSource = Enum.GetValues(typeof(MyEnum));

comboBox1.SelectedIndex = (int)MyEnum.Something;

comboBox1.SelectedIndex = Convert.ToInt32(MyEnum.Something);

Kedua pekerjaan ini untuk saya, apakah Anda yakin tidak ada hal lain yang salah?


2
Tidak yakin ini akan berhasil jika menggunakan nilai enum khusus, yaituenum MyEnum { Something = 47 }
Samantha Branham

0

Metode umum untuk menyetel enum sebagai sumber data untuk drop-down

Tampilan akan menjadi nama. Nilai yang dipilih adalah Enum itu sendiri

public IList<KeyValuePair<string, T>> GetDataSourceFromEnum<T>() where T : struct,IConvertible
    {
        IList<KeyValuePair<string, T>> list = new BindingList<KeyValuePair<string, T>>();
        foreach (string value in Enum.GetNames(typeof(T)))
        {
            list.Add(new KeyValuePair<string, T>(value, (T)Enum.Parse(typeof(T), value)));
        }
        return list;
    }

0

Itu selalu menjadi masalah. jika Anda memiliki Enum Tersortir, seperti dari 0 hingga ...

public enum Test
      one
      Two
      Three
 End

Anda dapat mengikat nama ke kotak kombo dan daripada menggunakan .SelectedValuepenggunaan properti.SelectedIndex

   Combobox.DataSource = System.Enum.GetNames(GetType(test))

dan

Dim x as byte = 0
Combobox.Selectedindex=x

0

Dalam Framework 4 Anda dapat menggunakan kode berikut:

Untuk mengikat enum MultiColumnMode ke kotak kombo misalnya:

cbMultiColumnMode.Properties.Items.AddRange(typeof(MultiColumnMode).GetEnumNames());

dan untuk mendapatkan indeks terpilih:

MultiColumnMode multiColMode = (MultiColumnMode)cbMultiColumnMode.SelectedIndex;

catatan: Saya menggunakan combobox DevExpress dalam contoh ini, Anda dapat melakukan hal yang sama di Win Form Combobox


0

Sedikit terlambat ke pesta ini,

Metode SelectedValue.ToString () harus menarik DisplayedName. Namun artikel ini DataBinding Enum dan juga With Descriptions menunjukkan cara praktis untuk tidak hanya memilikinya tetapi sebaliknya Anda dapat menambahkan atribut deskripsi khusus ke enum dan menggunakannya untuk nilai yang ditampilkan jika Anda mau. Sangat sederhana dan mudah dan sekitar 15 baris kode (kecuali Anda menghitung tanda kurung kurawal) untuk semuanya.

Ini adalah kode yang cukup bagus dan Anda dapat menjadikannya sebagai metode ekstensi untuk mem-boot ...


0

hanya gunakan transmisi dengan cara ini:

if((YouEnum)ComboBoxControl.SelectedItem == YouEnum.Español)
{
   //TODO: type you code here
}

0

Anda dapat menggunakan metode ekstensi

 public static void EnumForComboBox(this ComboBox comboBox, Type enumType)
 {
     var memInfo = enumType.GetMembers().Where(a => a.MemberType == MemberTypes.Field).ToList();
     comboBox.Items.Clear();
     foreach (var member in memInfo)
     {
         var myAttributes = member.GetCustomAttribute(typeof(DescriptionAttribute), false);
         var description = (DescriptionAttribute)myAttributes;
         if (description != null)
         {
             if (!string.IsNullOrEmpty(description.Description))
             {
                 comboBox.Items.Add(description.Description);
                 comboBox.SelectedIndex = 0;
                 comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
             }
         }   
     }
 }

Cara menggunakan ... Deklarasikan enum

using System.ComponentModel;

public enum CalculationType
{
    [Desciption("LoaderGroup")]
    LoaderGroup,
    [Description("LadingValue")]
    LadingValue,
    [Description("PerBill")]
    PerBill
}

Metode ini menunjukkan deskripsi dalam item kotak kombo

combobox1.EnumForComboBox(typeof(CalculationType));

0

Ini berhasil untuk saya:

comboBox1.DataSource = Enum.GetValues(typeof(MyEnum));
comboBox1.SelectedIndex = comboBox1.FindStringExact(MyEnum.something.ToString());
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.