Vor längerer Zeit habe ich in diesem Artikel berichtet wie man enum Werte über die DataSource Eigenschaft an eine Combobox binden kann.
Hier eine Darstellung einer solchen Bindung in einer normalen Windows Form:
Will man nun aber enum Werte in einem DataGridview an eine, als Combobox definierte, Spalte (DataGridViewComboBoxColumn) binden, geht das nicht ganz so einfach, und eben nicht so wie es in meinem oben erwähnten Artikel beschrieben ist.
Das Ergebnis soll so aussehen:
Wer schon einmal eine solche Tabelle programmiert hat, weiß, dass man nachdem man die DataSource Eigenschaft der DataGridViewComboBoxColumn zugewiesen hat, noch den ValueMember und den DisplayMember angeben muss (Siehe nachfolgende Abbildung).
Da wir die DataSource Eigenschaft bei der enum Variante über den Source Code zuweisen (es geht auch anders, dazu evtl. zu einem späteren Zeitpunkt mal mehr), müssen wir natürlich auch die beiden Eigenschaften DisplayMember und ValueMember aus dem Quellcode heraus zuweisen.
Nur wie heißen die denn ?
Und genau hier liegt das Problem, bzw. die hier beschriebene Lösung.
Diese Eigenschaften gibt es bei der ursprünglich von mir beschriebenen Lösung nicht.
Und daher müssen wir uns solche Eigenschaften bilden. Hierzu verwenden ich eine Helper Klasse die das notwendige implementiert. (Siehe nachfolgenden Source Code)
Hier nun der Code der Klassen
[Serializable] public class EnumHelper { public int Key { get; set; } public string Value { get; set; } public static IEnumerable<ValueListItem> CreateDataSourceFromEnum(Type t) { var list = new List<ValueListItem>(); Array aEnum = Enum.GetValues(t); foreach (var array in aEnum) { var vi = new ValueListItem { Key = (int) array, Value = array.ToString() }; list.Add(vi); } return list; } public static IEnumerable<EnumHelper> DataSourceFromEnum(Type t) { var list = new List<EnumHelper>(); Array aEnum = Enum.GetValues(t); foreach (var array in aEnum) { var vi = new EnumHelper { Key = (int) array, Value = array.ToString() }; list.Add(vi); } return list; } } [Serializable] public class ValueListItem { public int Key { get; set; } public string Value { get; set; } }
Und so kann man die Helper Klasse verwenden um die DataSource Eigenschaft sowie die ValueMember und DisplayMember Eigenschaften zuzuweisen.
private void InitDgv() { bereichDataGridViewTextBoxColumn.DataSource = EnumHelper.DataSourceFromEnum(typeof(EntladungsTyp)); bereichDataGridViewTextBoxColumn.DisplayMember = "Value"; bereichDataGridViewTextBoxColumn.ValueMember = "Key"; }
Wichtiger Hinweis
Ich verwende diese Klasse bereits seit mehreren Jahren und weiß nicht mehr genau ob ich von irgend jemand etwas übernommen und überarbeitet habe, oder ob ich das im stillen Kämmerchen ausgebrütet habe.
Eine kurze Recherche im Internet hat keine direkten Ergebnisse / Quellen hervorgebracht. Es gibt zwar einige Beiträge die sich auch mit enum Helper Klassen beschäftigen, aber die, welche ich gerade gesehen habe, beschäftigen sich nicht genau mit dem von mir hier beschriebenen Thema, so dass ich zur Zeit keine Angaben über eventuelle Quellen, die mich inspiriert haben könnten, machen kann.
Aber wenn jemand erkennt dass ich Code von wem auch immer verwendet habe, hinterlasst dass bitte in einem Kommentar, so dass sich eventuell fehlende Quellnachweise schließen.
Habe mit dem Problem auch rumgekämpft. Unten ist meine Variante.
Beim Verwenden in einer DataGridViewComboBoxColumn
sollte man drauf achten, das die GridView-Spalte den Int32 (=int) Typ hat.
Sonst kommt der Fehler „….Cell Wert ist ungültig“ oder so.
Dieser Fehler kommt auch dann, wenn in der GridView-Spalte ein
Wert gespeichert ist, der in der Enum-Auflistung nicht vorkommt.
Allerdings ist das kein Problem dieser Klasse, sondern von DataGridViewComboBoxColumn. Aus meiner Sicht könnte es M$…
besser lösen, oder zumindest eine vernünftigere Fehlermeldung ausgeben.
Schöne Grüße
Ich habe deinen Kommentar zusammengefasst und hoffe dass jetzt alle Spitzen Klammern richtig ausgegeben werden 🙂
Viele Dank für diese Variante.
Allerdings setzt diese Variante Linq voraus was erst mit .NET Framework 3.5 implementiert wurde.
Also überall da, und das gibt es tatsächlich noch öfter als man denkt, wo der entsprechende Framework nicht verfügbar ist und man noch mit FW 2.0 auskommen muss, geht diese Variante leider nicht.
Viele Grüße
HÜ
Falls wir schon dabei sind alles richtig zu machen 🙂
bitte mein vorherigen Eintrag entfernen, da waren
noch andere Übertragungsfehler. Hier die korrekte Variante
von „EnumDataSource“, die auch ohne LINQ auskommen kann:
Falls man bereits LINQ verwendet, kann man die Einträge
zusätzlich alphabetisch sortieren. Dazu muss man die Zeile
this.AddRange(array);
durch
ersetzen.
Verwendung:
Text kann man jetzt mit ‚cbo.Text‘ auslesen und den Wert mit ‚cbo.SelectedValue‘.
Das funktioniert auch mit der Klasse DataGridViewComboBoxColumn in einem DataGridView.
Schöne Grüße
PK
Zu dem ersten Beispiel: Welche Klasse bzw. welche Methode muss ich wo aufrufen…
Hallo Kalle,
kannst du deine Frage etwas präzisieren?
Lg
HP
Hallo Peter,
danke für deine schnelle Antwort. Aber ich habe es hinbekommen, hatte in dem Beispiel nur eine Zeile übersehen.
MFG
Ich hatte da auch mal was gebaut. In meinem Beispiel binde ich die Aufzählung in XAML an ein ComboBox Control.
upps, sorry der Artikel ist ja schon ein paar Tage alt : )
Hi Mario!
Sind wir nicht alle ein paar Tage älter! 🙂
Lg
HP
Schönes Codebeispiel Hans-Peter, danke dafür.
Das Anwendungsbeispiel könnte für den Fall eines gebundenen DataGridViews in InitDgv() noch um die Eigenschaft DataPropertyName ergänzt werden.
Angenommen, die DataTable für die DataSource der BindingSource beinhaltet den Entladungstyp im gleichnamigen Feld „Entladungstyp“, muss dieser Feldname dem Combo als DataPropertyName zugewiesen werden, damit bei der Anzeige vorhandener Datensätze der richtige Wert des Combos ausgewählt wird:
bereichDataGridViewTextBoxColumn.DataPropertyName = „Entladungstyp“;
Grüssle, Herbert
Prueba con esto, sin necesidad de crear nada XD
Enum RelacionE
Uno=1
Dos=2
Tres=3
End Enum
Dim enumvalues = New List(Of RelacionE)([Enum].GetValues(GetType(RelacionE)))
Dim items = enumvalues.ToDictionary(Function(k) [Enum].GetName(GetType(RelacionE), k))
Relacion.DataSource = items.ToList
Relacion.DisplayMember = "Key"
Relacion.ValueMember = "Value"