Bir numaralandırmayı bir WinForms birleşik giriş kutusuna bağlama ve ardından ayarlama


122

WinForms'da bir enum'un birleşik giriş kutusuna nasıl bağlanacağı sorusuna birçok kişi yanıt verdi. Bunun gibi:

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

Ancak, gerçek değeri görüntülenecek şekilde ayarlayamadan bu oldukça işe yaramaz.

Denedim:

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

Ben de denedim:

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

Bunun nasıl yapılacağı hakkında herhangi bir fikri olan var mı?


2
Neden onun yerine ComboBox.SelectedValue denemiyorsunuz?
Oliver Friedrich

5
Sorunuz yanıtlandıysa, gerçekten bir yanıt seçmelisiniz.
Ryan The Leach

Bir numaralandırmanın veri bağlamasının amacı pek açık değildir. Bir enum, çalışma sırasında büyük olasılıkla değişmeyecektir. Ayrıca, combobox'un öğe koleksiyonunu numaralamanın tüm değerleriyle dolduracak bir genişletme yöntemi de yazabilirsiniz.
Andreas


@OliverFriedrich benim için SelectedValuebir neden oluyor InvalidOperationException. " SelectedValueA ListControlile boş olarak ayarlanamaz ValueMember."
Tyler

Yanıtlar:


161

Enum

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

Açılır değerleri buradan ayarlama

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

Seçili öğeden numaralandırmayı alma

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

5
Teşekkürler, bu benim için çalışıyor. Triparse'nin bir .net 4.0 ifadesi olduğunu unutmayın.
real_yggdrasil

Benim için SelectedValue her zaman null. Görünüşe göre birleşik giriş kutusu kullanıma hazır değil. (MyEnum) this.GridView.CurrentRow.Cells [ "comboColumnCell"]. değer. Değeri görebiliyorum ama dahili olarak boş işaretçi istisnası atıyor
ssal

3
Bu tam olarak OP'nin kullanmak istemediği yoldur. Sorun, kullanıcıya adın her değerin kodunda gösterilmesidir; bu, yeniden düzenlemeye tabidir ve çoğu zaman kullanıcı dostu değildir.
Alejandro

5
Neden Ayrıştırmak yerine TryParse kullanmalı? ... var status (Status) Enum.Parse (typeof (Status), cbStatus.SelectedValue.ToString ()); ... Enum'u birleşik giriş kutusuna bağladınız, böylece değerin geçerli bir enum değeri olması gerektiğini ve eğer o zaman bir şeyler çok ters gitmiştir ve muhtemelen bir istisna istiyorsunuz.
bytedev

1
Bu neden unutulmaya davet ediliyor? Soru, birleşik giriş kutusunun seçilen değerinin, numaralandırma değerlerinden birini kullanarak programlı olarak nasıl ayarlanacağıdır.
Tyler

39

Basitleştirmek için:

İlk önce bu komutu başlatın: (örn. Sonra InitalizeComponent())

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

Comboox'ta seçili öğeyi almak için:

YourEnum enum = (YourEnum) yourComboBox.SelectedItem;

Birleşik giriş kutusu için bir değer ayarlamak isterseniz:

yourComboBox.SelectedItem = YourEnem.Foo;

2
Bu, Görüntü değeri Değer üyesi ile aynı olduğu sürece çalışır, aksi halde değildir.
Script Efendisi

15

Kod

comboBox1.SelectedItem = MyEnum.Something;

Tamam, sorun DataBinding'de bulunmalıdır. DataBinding atamaları, yapıcıdan sonra, esas olarak birleşik giriş kutusu ilk kez gösterildiğinde gerçekleşir. Load olayında değeri ayarlamayı deneyin. Örneğin, şu kodu ekleyin:

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

Ve çalışıp çalışmadığını kontrol edin.


12

Deneyin:

comboBox1.SelectedItem = MyEnum.Something;

DÜZENLEMELER:

Maalesef bunu zaten denedin. Ancak, comboBox'ım bir DropDownList olarak ayarlandığında benim için çalıştı.

İşte benim için çalışan tam kodum (hem DropDown hem de DropDownList ile):

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

ilginç, `comboBox1.SelectedItem = BlahEnum.Blue; '' yapabilmeniz harika bir şey ama ya combobox'taki şeylerin dizge olmasını istiyorsanız, örneğin bir combobox öğesinin" çiğnenebilir vitamin hapı "olmasını istiyorsanız?
barlop

11

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

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

Bu değerleri bir dizeye eşlemek için bir yapıya sahip olmanız gerekir:

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

Şimdi, tüm numaralandırmaların bir dizeye eşlendiği bir nesne dizisi döndür:

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

Birleşik giriş kutunuzu doldurmak için aşağıdakileri kullanın:

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

Sadece bir işleve aktarmak istemeniz durumunda numaralandırma türünü almak için bir işlev oluşturun

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

ve sonra iyi olmalısın :)


+1 güzel çözüm. Son zamanlarda bu çok problemi yaşadım ve benzer şekilde çözüldü (sadece a Tupleyerine). Hem enum değerini hem de açıklamayı özelliklere dönüştürür, ardından bir numberCB.DisplayProperty = "Caption"; ` eklerim ve numberCB.ValueProperty = "Num"böylece SelectedValuedoğrudan kullanıp ona bağlanabilirsiniz.
Alejandro

IMHO, belki daha eksiksiz örnek kaynak kodu, eğer bir aramadaki tüm satırları filtrelemek için kullanılan ComboBox'a "Tümünü" Ekle / "Tümünü Seç" seçeneği gibi işlevler de varsa.
Kiquenet

5

Bunu dene:

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

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

StoreObject, Store MyEnum değeri için StoreObjectMyEnumField özelliğine sahip nesne örneğimdir.


1
Şimdiye kadarki en iyi yaklaşım bu ama benim için işe yaramadı. "SelectedValue" yerine "SelectedItem" kullanmak zorunda kaldım
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;
    }

ne demek istiyorsun ? Yorumunu anlamadım. bu uzatma yöntemi işe yarıyor
Mickey Perlstein

Bu, sıralama numaralarınızın VEYA FLag'lere izin verip vermediğine bağlıdır. eğer öyleyse Tümü olarak adlandırılan 255 olan bir bayrak ekleyebilir ve varsayılanı oluşturan Tümü enum1 olarak işlevi çağırabilirsiniz. ie comboBox1.FillByEnumOrderByName (MyEnum.All)
Mickey Perlstein

Bunun gibi herhangi bir seçenek: var l = values.OrderBy (x => x.Value) .ToList (); l.Insert (0, "Tümü");
Kiquenet

numaram enum A {ördek = 0, kuğu = 1, joker = 3}; sisteminiz benim durumum için çalışmayacak.
Mickey Perlstein

3

bu, enum öğesini combobox'a yüklemek için bir çözümdür:

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

Ve sonra enum öğesini metin olarak kullanın:

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

3

@Amir Shenouda'nın cevabına göre şunu elde ettim:

Enum'un tanımı:

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

Açılır değerleri buradan ayarlama:

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

Seçili öğeden numaralandırmayı alma:

Status? status = cbStatus.SelectedValue as Status?;

2
neden nullable kullanıyorsunuz? Sen null kullanmak açık dökümü (parantez döküm) kullanın ve could not
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, belki daha eksiksiz örnek kaynak kodu, eğer bir aramadaki tüm satırları filtrelemek için kullanılan ComboBox'a "Tümünü" Ekle / "Tümünü Seç" seçeneği gibi işlevler de varsa.
Kiquenet


1

Listenize bağlayabileceğiniz aşağıdaki yardımcı yöntemi kullanıyorum.

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

Numaralamayı dize listesine dönüştürün ve bunu comboBox'a ekleyin

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

SelectedItem kullanarak görüntülenen değeri ayarlayın

comboBox1.SelectedItem = SomeEnum.SomeValue;

1

Bunların hiçbiri benim için işe yaramadı, ancak bu işe yaradı (ve her bir numaralamanın adı için daha iyi bir tanıma sahip olma ek yararı vardı). Net güncellemelerinden kaynaklanıp kaynaklanmadığından emin değilim, ancak bunun en iyi yol olduğunu düşünüyorum. Şunlara bir referans eklemeniz gerekecek:

System.ComponentModel kullanarak;

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

Ardından verilere erişmek istediğinizde şu iki satırı kullanın:

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

1

Bu muhtemelen diğer tüm yanıtlar arasında asla görülmeyecektir, ancak bu benim bulduğum kod, bu, DescriptionAttributevarsa, kullanmanın yararı var, aksi takdirde enum değerinin adını kullanmanın yararı var.

Bir sözlük kullandım çünkü hazır yapılmış bir anahtar / değer öğe kalıbı var. A List<KeyValuePair<string,object>>da işe yarar ve gereksiz karmalar olmadan çalışır, ancak bir sözlük daha temiz kod üretir.

A değerine sahip ve gerçek MemberTypeolan üyeler alıyorum Field. Bu, yalnızca numaralandırma değerleri olan üyelerden oluşan bir dizi oluşturur. Bir enum başka alanlara sahip olamayacağı için bu sağlamdır.

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;

iyi çalışmalı ... Bunun SelectedItemboş olduğunu nasıl anlarsın ?


Hata ayıklayıcıda kontrol edebilirim. Sanırım SelectedItem türü nesne, yani başvuru türü ve numaralandırmalar değer türleri. Yine de derleyicinin bunu yakalamasını beklerdim.

0

"FindString .." işlevlerini kullanabilirsiniz:

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

Comboox için veri kaynağı olarak KeyValuePair değerlerinin bir listesini kullanabilirsiniz. Enum türünü belirtebileceğiniz bir yardımcı yönteme ihtiyacınız olacak ve IEnumerable> döndürüyor burada int enum değeridir ve string, enum değerinin adıdır. Kombine kutunuzda, DisplayMember özelliğini 'Anahtar' ve ValueMember özelliğini 'Değer' olarak ayarlayın. Değer ve Anahtar, KeyValuePair yapısının genel özellikleridir. Daha sonra SelectedItem özelliğini yaptığınız gibi bir enum değerine ayarladığınızda çalışmalıdır.


0

Şu anda DataSource yerine Öğeler özelliğini kullanıyorum, bu, her bir enum değeri için Add'i çağırmam gerektiği anlamına geliyor, ancak bu küçük bir enum ve yine de geçici kodu.

Ardından, Convert.ToInt32'yi değer üzerinde yapabilir ve SelectedIndex ile ayarlayabilirim.

Geçici çözüm, ancak şimdilik YAGNI.

Fikirler için teşekkürler, bir dizi müşteri geri bildirimi aldıktan sonra uygun sürümü yaptığımda muhtemelen bunları kullanacağım.



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

comboBox1.SelectedIndex = (int)MyEnum.Something;

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

Bunların ikisi de benim için çalışıyor, yanlış bir şey olmadığına emin misin?


2
Özel enum değerleri kullanarak eğer emin değil bu işe yarar, yanienum MyEnum { Something = 47 }
Samantha Branham

0

Açılır listeler için veri kaynağı olarak bir numaralandırmayı ayarlamak için genel yöntem

Ekran adı olacaktır. Seçilen değer Enum'un kendisi olacaktır

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

Bu her zaman bir sorundu. 0 ile ... gibi bir Sıralanmış Enumunuz varsa

public enum Test
      one
      Two
      Three
 End

isimleri birleşik giriş kutusuna bağlayabilir ve .SelectedValueözellik kullanımı yerine.SelectedIndex

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

ve

Dim x as byte = 0
Combobox.Selectedindex=x

0

Framework 4'te aşağıdaki kodu kullanabilirsiniz:

MultiColumnMode numaralandırmasını örneğin birleşik giriş kutusuna bağlamak için:

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

ve seçilen dizini almak için:

MultiColumnMode multiColMode = (MultiColumnMode)cbMultiColumnMode.SelectedIndex;

not: Bu örnekte DevExpress combobox kullanıyorum, aynısını Win Form Combobox'ta da yapabilirsiniz


0

Bu partiye biraz geç

SelectedValue.ToString () yöntemi DisplayedName'i çekmelidir. Bununla birlikte, bu makale DataBinding Enum ve With Descriptions , yalnızca buna sahip olmanın kullanışlı bir yolunu göstermekle kalmaz, bunun yerine numaralandırmaya özel bir açıklama özelliği ekleyebilir ve isterseniz görüntülenen değeriniz için kullanabilirsiniz. Çok basit ve kolay ve her şey için yaklaşık 15 satırlık kod (kaşlı ayraçları saymazsanız).

Oldukça şık bir koddur ve onu önyüklemek için bir uzantı yöntemi yapabilirsiniz ...


0

yayınlamayı yalnızca bu şekilde kullanın:

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

0

Bir uzatma yöntemi kullanabilirsiniz

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

Nasıl kullanılır ... Enum bildir

using System.ComponentModel;

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

Bu yöntem, Birleşik giriş kutusu öğelerindeki açıklamayı gösterir

combobox1.EnumForComboBox(typeof(CalculationType));

0

Bu benim için çalıştı:

comboBox1.DataSource = Enum.GetValues(typeof(MyEnum));
comboBox1.SelectedIndex = comboBox1.FindStringExact(MyEnum.something.ToString());
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.