Binden Sie eine Aufzählung an ein WinForms-Kombinationsfeld und legen Sie sie fest


122

Viele Leute haben die Frage beantwortet, wie eine Aufzählung in WinForms an ein Kombinationsfeld gebunden werden kann. Es ist wie folgt:

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

Aber das ist ziemlich nutzlos, ohne den tatsächlichen Wert für die Anzeige einstellen zu können.

Ich habe versucht:

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

Ich habe auch versucht:

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

Hat jemand Ideen, wie das geht?


2
Warum probieren Sie nicht stattdessen einfach die ComboBox.SelectedValue aus?
Oliver Friedrich

5
Wenn Ihre Frage beantwortet wurde, sollten Sie wirklich eine Antwort auswählen.
Ryan The Leach

Der Punkt der Datenbindung einer Aufzählung ist nicht ganz klar. Eine Aufzählung wird sich zur Laufzeit wahrscheinlich nicht ändern. Sie können auch eine Erweiterungsmethode schreiben, die die Elementsammlung der Combobox mit allen Werten der Aufzählung füllt.
Andreas


@OliverFriedrich SelectedValueverursacht ein InvalidOperationExceptionfür mich. "Kann das SelectedValuein a nicht ListControlmit einem leeren setzen ValueMember."
Tyler

Antworten:


161

Die Aufzählung

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

Festlegen der Dropdown-Werte

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

Abrufen der Aufzählung aus dem ausgewählten Element

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

5
Danke, das funktioniert bei mir. Beachten Sie, dass Tryparse eine .net 4.0-Anweisung ist.
real_yggdrasil

Für mich ist SelectedValue immer null. Es scheint, dass die Combobox nicht initialisiert wird. (myEnum) this.GridView.CurrentRow.Cells ["comboColumnCell"]. Wert. Ich kann Wert sehen, aber intern
löst

3
Dies ist genau die Art und Weise, die das OP nicht verwenden möchte. Problem ist, dass dem Benutzer der Name im Code jedes Werts angezeigt wird, der einer Umgestaltung unterliegt und meistens nicht benutzerfreundlich ist.
Alejandro

5
Warum TryParse anstelle von Parse verwenden? ... var status (Status) Enum.Parse (typeof (Status), cbStatus.SelectedValue.ToString ()); ... Sie haben die Aufzählung an die Combobox gebunden, damit Sie wissen, dass der Wert ein gültiger Aufzählungswert sein muss und wenn Es ist nicht so, dass etwas sehr schief gelaufen ist und Sie wahrscheinlich eine Ausnahme wollen.
Bytedev

1
Warum wird dies in Vergessenheit geraten? Die Frage ist, wie der ausgewählte Wert der Combobox mithilfe eines der Werte der Aufzählung programmgesteuert festgelegt werden kann.
Tyler

39

Vereinfachen:

Initialisieren Sie zuerst diesen Befehl: (zB nach InitalizeComponent())

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

So rufen Sie das ausgewählte Element in der Combobox ab:

YourEnum enum = (YourEnum) yourComboBox.SelectedItem;

Wenn Sie einen Wert für die Combobox festlegen möchten:

yourComboBox.SelectedItem = YourEnem.Foo;

2
Dies funktioniert so lange, wie der Anzeigewert mit dem Wertelement identisch ist, andernfalls nicht.
Lord of Scripts

15

Der Code

comboBox1.SelectedItem = MyEnum.Something;

Ist in Ordnung, muss das Problem in der Datenbindung liegen. DataBinding-Zuweisungen erfolgen nach dem Konstruktor, hauptsächlich beim ersten Anzeigen der Combobox. Versuchen Sie, den Wert im Load-Ereignis festzulegen. Fügen Sie beispielsweise diesen Code hinzu:

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

Und prüfen Sie, ob es funktioniert.


12

Versuchen:

comboBox1.SelectedItem = MyEnum.Something;

EDITS:

Hoppla, das hast du schon versucht. Es hat jedoch bei mir funktioniert, als meine ComboBox auf DropDownList eingestellt war.

Hier ist mein vollständiger Code, der für mich funktioniert (sowohl mit DropDown als auch mit 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;
    }
}

Interessant, es ist großartig, dass Sie "comboBox1.SelectedItem = BlahEnum.Blue" ausführen können. Aber was ist, wenn Sie möchten, dass die Dinge in der Combobox Zeichenfolgen sind, z.
Barlop

11

Angenommen, Sie haben die folgende Aufzählung

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

Sie benötigen eine Struktur, um diese Werte einer Zeichenfolge zuzuordnen:

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

Geben Sie nun ein Array von Objekten mit allen Aufzählungen zurück, die einer Zeichenfolge zugeordnet sind:

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

Verwenden Sie Folgendes, um Ihr Kombinationsfeld zu füllen:

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

Erstellen Sie eine Funktion, um den Aufzählungstyp abzurufen, falls Sie ihn an eine Funktion übergeben möchten

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

und dann solltest du ok sein :)


+1 schöne Lösung. Hatte kürzlich genau dieses Problem und löste es auf ähnliche Weise (nur mit einem Tuplestattdessen). Ich würde sowohl den Enum-Wert als auch die Beschreibung in Eigenschaften umwandeln und dann ein numberCB.DisplayProperty = "Caption"; ` hinzufügen , numberCB.ValueProperty = "Num"damit Sie es SelectedValuedirekt verwenden und daran binden können.
Alejandro

IMHO, vielleicht vollständigerer Beispielquellcode, wenn es auch Funktionen wie "Alle hinzufügen" / "Alle auswählen" zu ComboBox gibt, mit denen alle Zeilen in einer Suche gefiltert werden.
Kiquenet

5

Versuche dies:

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

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

StoreObject ist mein Objektbeispiel mit der StoreObjectMyEnumField-Eigenschaft für den Store MyEnum-Wert.


1
Dies ist bei weitem der beste Ansatz, aber so wie er ist, hat er bei mir nicht funktioniert. Ich musste "SelectedItem" anstelle von "SelectedValue" verwenden
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;
    }

Was meinst du ? Ich habe Ihren Kommentar nicht verstanden. Diese Erweiterungsmethode funktioniert
Mickey Perlstein

Dies hängt davon ab, ob Ihre Aufzählungsnummern ODER FLags zulassen. Wenn ja, können Sie ein Flag mit dem Namen All hinzufügen, das 255 heißt, und die Funktion mit All als enum1 aufrufen, wodurch die Standardeinstellung erstellt wird. dh comboBox1.FillByEnumOrderByName (MyEnum.All)
Mickey Perlstein

Jede Option wie diese: var l = values.OrderBy (x => x.Value) .ToList (); Einfügen (0, "Alle");
Kiquenet

meine Aufzählung ist Aufzählung A {duck = 0, swan = 1, joker = 3}; Ihr System wird für meine Situation nicht funktionieren.
Mickey Perlstein

3

Dies ist die Lösung zum Laden von Enum-Elementen in die Combobox:

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

Verwenden Sie dann das Aufzählungselement als Text:

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

3

Basierend auf der Antwort von @Amir Shenouda komme ich zu folgendem Ergebnis:

Enums Definition:

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

Festlegen der Dropdown-Werte daraus:

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

Abrufen der Aufzählung aus dem ausgewählten Element:

Status? status = cbStatus.SelectedValue as Status?;

2
Warum nullable verwenden? Sie könnten explizites Casting (Casting in Klammern) und nicht nullable verwenden
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, vielleicht vollständigerer Beispielquellcode, wenn es auch Funktionen wie "Alle hinzufügen" / "Alle auswählen" zu ComboBox gibt, mit denen alle Zeilen in einer Suche gefiltert werden.
Kiquenet


1

Ich verwende die folgende Hilfsmethode, die Sie an Ihre Liste binden können.

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

Konvertieren Sie die Aufzählung in eine Liste von Zeichenfolgen und fügen Sie diese der ComboBox hinzu

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

Stellen Sie den angezeigten Wert mit selectedItem ein

comboBox1.SelectedItem = SomeEnum.SomeValue;

1

Keines davon funktionierte für mich, aber das tat es (und es hatte den zusätzlichen Vorteil, eine bessere Beschreibung für den Namen jeder Aufzählung zu haben). Ich bin mir nicht sicher, ob es an .net-Updates liegt oder nicht, aber ich denke, dies ist der beste Weg. Sie müssen einen Verweis hinzufügen auf:

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

Wenn Sie dann auf die Daten zugreifen möchten, verwenden Sie diese beiden Zeilen:

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

1

Dies wird wahrscheinlich nie unter all den anderen Antworten zu sehen sein, aber dies ist der Code, den ich mir ausgedacht habe. Dies hat den Vorteil, dass ich den verwende DescriptionAttribute falls vorhanden, verwendet wird, ansonsten aber der Name des Aufzählungswerts selbst.

Ich habe ein Wörterbuch verwendet, weil es ein fertiges Schlüssel- / Wertelementmuster enthält. EINList<KeyValuePair<string,object>> würde auch funktionieren und ohne unnötiges Hashing, aber ein Wörterbuch sorgt für saubereren Code.

Ich bekomme Mitglieder, die ein MemberTypevon haben Fieldund die buchstäblich sind. Dadurch wird eine Folge von nur Mitgliedern erstellt, die Aufzählungswerte sind. Dies ist robust, da eine Aufzählung keine anderen Felder haben kann.

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;

sollte gut funktionieren ... Wie können Sie feststellen, dass SelectedItemdas null ist?


Ich kann es im Debugger überprüfen. Ich gehe davon aus, dass der Typ von SelectedItem ein Objekt ist, dh ein Referenztyp, und Aufzählungen sind Werttypen. Obwohl ich erwartet hätte, dass der Compiler das fängt.

0

Sie können die Funktionen "FindString .." verwenden:

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

Sie können eine Liste von KeyValuePair-Werten als Datenquelle für die Combobox verwenden. Sie benötigen eine Hilfsmethode, mit der Sie den Aufzählungstyp angeben können. Sie gibt IEnumerable> zurück, wobei int der Wert von enum und string der Name des Aufzählungswerts ist. Setzen Sie in Ihrer Combobox die DisplayMember-Eigenschaft auf 'Key' und die ValueMember-Eigenschaft auf 'Value'. Wert und Schlüssel sind öffentliche Eigenschaften der KeyValuePair-Struktur. Wenn Sie dann die SelectedItem-Eigenschaft wie Sie auf einen Aufzählungswert setzen, sollte dies funktionieren.


0

Im Moment verwende ich die Items-Eigenschaft anstelle der DataSource. Dies bedeutet, dass ich Add für jeden Aufzählungswert aufrufen muss, aber es ist eine kleine Aufzählung und der temporäre Code trotzdem.

Dann kann ich einfach Convert.ToInt32 für den Wert ausführen und ihn mit SelectedIndex festlegen.

Temporäre Lösung, aber YAGNI vorerst.

Prost auf die Ideen, ich werde sie wahrscheinlich verwenden, wenn ich die richtige Version mache, nachdem ich eine Runde Kundenfeedback erhalten habe.



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

comboBox1.SelectedIndex = (int)MyEnum.Something;

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

Beide Arbeiten für mich sind Sie sicher, dass nichts anderes falsch ist?


2
Ich bin mir nicht sicher, ob dies funktionieren würde, wenn benutzerdefinierte Aufzählungswerte verwendet würden, dhenum MyEnum { Something = 47 }
Samantha Branham

0

Generische Methode zum Festlegen einer Aufzählung als Datenquelle für Dropdowns

Anzeige wäre Name. Der ausgewählte Wert wäre Enum selbst

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

Das war immer ein Problem. Wenn Sie eine sortierte Aufzählung haben, wie von 0 bis ...

public enum Test
      one
      Two
      Three
 End

Sie können Namen an die Combobox binden und stattdessen die Verwendung von .SelectedValueEigenschaften verwenden.SelectedIndex

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

und das

Dim x as byte = 0
Combobox.Selectedindex=x

0

In Framework 4 können Sie den folgenden Code verwenden:

So binden Sie die MultiColumnMode-Enumeration an die Combobox, zum Beispiel:

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

und um den ausgewählten Index zu erhalten:

MultiColumnMode multiColMode = (MultiColumnMode)cbMultiColumnMode.SelectedIndex;

Hinweis: In diesem Beispiel verwende ich die DevExpress-Combobox. Sie können dies auch in der Win Form Combobox tun


0

Ein bisschen spät zu dieser Party,

Die SelectedValue.ToString () -Methode sollte den DisplayedName abrufen. Dieser Artikel DataBinding Enum und auch With Descriptions zeigt jedoch eine praktische Möglichkeit, dies nicht nur zu haben, sondern Sie können der Enum stattdessen ein benutzerdefiniertes Beschreibungsattribut hinzufügen und es für Ihren angezeigten Wert verwenden, wenn Sie dies bevorzugen. Sehr einfach und leicht und ungefähr 15 Codezeilen (es sei denn, Sie zählen die geschweiften Klammern) für alles.

Es ist ein ziemlich raffinierter Code und Sie können ihn zu einer Erweiterungsmethode zum Booten machen ...


0

Verwenden Sie Casting nur so:

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

0

Sie können eine Erweiterungsmethode verwenden

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

Wie man ... Enum deklariert

using System.ComponentModel;

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

Diese Methode zeigt die Beschreibung in Kombinationsfeldelementen an

combobox1.EnumForComboBox(typeof(CalculationType));

0

Das hat bei mir funktioniert:

comboBox1.DataSource = Enum.GetValues(typeof(MyEnum));
comboBox1.SelectedIndex = comboBox1.FindStringExact(MyEnum.something.ToString());
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.