Enum

  • VB.NET

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Ich möchte in einem Container die Mitglieder eines Enums auflisten. Das ist kein Problem wenn ich den Enum-Namen (MouseSelectionRules) hartcodiere:

    VB.NET-Quellcode

    1. For Each b As Byte In [Enum].GetValues(GetType(MouseSelectionRules))
    2. Dim o As New RadioButton
    3. o.Text = [Enum].GetName(GetType(MouseSelectionRules), b)
    4. o.Tag = b
    5. FlowLayoutPanel1.Controls.Add(o)
    6. Next b

    Was muss ich aber tun, wenn ich den Enum-Namen übergeben möchte? So in etwa:

    TextBox1.Text = "MouseSelectionRules"
    Dim myEnum As [Enum] = TextBox1.Text (<-- klappt natürlich nicht)

    und dann meine kleine Schleife von oben so verändert starte

    VB.NET-Quellcode

    1. For Each b As Byte In [Enum].GetValues(GetType(myEnum))
    2. ...


    Hilfe
    Philipp
    Enums sind hardcodiert, und da ist nix zu wollen.

    Wenn der User iwelche Daten ändern dürfen soll, dann sinds keine Enums, sondern sind Daten, und das ist dann eine Frage der Datenmodellierung.
    Man kann etwa mit Leichtigkeit ein Array mit einer Enumeration assoziieren, und der User darf die Namen ins Array eingeben, und mit den Enum-Werten als Index ruft man die auch wieder ab.
    Aber sowas muß auch abgespeichert werden, und vmtl. gibts noch mehr Daten, und dann braucht man eh ein typisiertes Dataset, und dort würdeman dann statt des Enums eine Lookup-DataTable anlegen, die exakt dasselbe verhackstückt wie das Enum, nur die Werte der DataTable sind nicht hardcodet.
    Der User soll keine (Enum-)Werte ändern, er soll die nur sehen. Eine Auflistung, das ist alles. Ich möchte das ganze gerne als UserControl aufbauen. Ein Usercontrol dem man den Namen des Typs mitgibt und dass dann alle Member auflistet.
    Ach so war das gemeint.
    System.Type bietet die nötigen Dinge dafür:

    VB.NET-Quellcode

    1. 'Zwei Beispiele für Enums:
    2. Enum TestEnum1 As Integer
    3. None = 0
    4. One = 1
    5. Two = 2
    6. End Enum
    7. Enum TestEnum2 As Integer
    8. Three = 3
    9. Four = 4
    10. Five = 5
    11. End Enum
    12. 'Eine Testfunktion
    13. Sub Test() Handles Me.MouseDown
    14. Foo(GetType(TestEnum1)) 'GetType() gibt eine System.Type-Instanz zurück, die den angegebenen Typ beschreibt.
    15. Foo(GetType(TestEnum2))
    16. End Sub
    17. Sub Foo(ByVal Bar As Type)
    18. If Not Bar.IsEnum Then 'Nur für den Fall, dass die Funktion fälschlicherweise mit einem ungültigen Typ aufgerufen wurde.
    19. Throw New ArgumentException("Parameter 'Bar' muss ein Enum-Typ sein!", "Bar")
    20. End If
    21. Dim Names = Bar.GetEnumNames().GetEnumNames 'gibt ein String-Array mit den Namen der Werte im Enum zurück.
    22. MessageBox.Show(String.Join(Environment.NewLine, Names)) 'Hier zum Test ausgeben.
    23. End Sub


    Edit:
    Wenn man die String-Darstellung wieder zurückwandeln möchte, wird's aber etwas komplizierter.
    Ich würde vorschlagen, anstelle von .GetEnumNames() die Funktion .GetEnumValues() zu verwenden.
    Das gibt ein untypisiertes Array zurück, in dem sich alle Werte befinden (Nicht die Namen der Werte, sondern die Werte).
    Diese Werte kannst Du in ein typisiertes [Enum]-Array kopieren und dann alle Einträte mit .ToString() in einen String konvertieren und so anzeigen.
    Beim Auswählen hast Du ja den Index des ausgewählten Elements. Mit dem Index holst Du einfach das Element aus dem Array und hinterlegst es einer Property vom Typ [Enum].
    So in der Richtung:

    VB.NET-Quellcode

    1. Public ReadOnly Property SelectedValue As [Enum]
    2. Get
    3. Return AllValues(_SelectedIndex)
    4. End Get
    5. End Property
    6. Dim AllValues As [Enum]()
    7. Public Sub SetValues(ByVal EnumType As Type)
    8. Dim EnumValues = EnumType.GetEnumValues
    9. AllValues = New [Enum](EnumValues.Length - 1) {}
    10. Array.Copy(EnumValues, AllValues, EnumValues.Length)
    11. End Sub


    Das Problem, das Du haben wirst, ist aber, dass Du Einen Wert irgendeines Enum-Typs zurückbekommst.
    Das musst Du selbst wieder zurückcasten.
    Zum Beispiel mit Dim Foo = DirectCast(DeinControl.SelectedValue, TestEnum1)
    Wenn Du das UserControl für fixe Enums verwendest, dann ist das OK.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Niko Ortner“ ()

    @Philipp66:
    brauche ich für TestEnum1 eine Variable

    Also wenn Du den Edit liest, ist das dann, bezogen auf meinen letzten Satz, nicht OK?
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    Hey Niko, danke nochmal für die Mühe. Das ist aber trotzdem nicht das, was ich haben wollte. Oder aber doch und ich habe es nur nicht verstanden. Auch gut möglich. In der Zwischenzeit ist mir aber selber eingefallen, wie es geht. Und zwar so:

    Hier definiere ich die Variable
    Dim myEnum As Type = GetType(MouseSelectionRules)

    und kann dann damit so weiterarbeiten:
    For Each b In [Enum].GetValues(myEnum)
    ...

    :) Philipp
    @Philipp66: Ich denke, das hast Du wirklich falsch verstanden.
    Wo Du Dim myEnum As Type = GetType(MouseSelectionRules) verwendest, steht bei mir halt SetValues(GetType(MouseSelectionRules)).
    Ich habe das in eine andere Funktion ausgelagert, da das bei Dir auch so passieren wird, wenn Du ein UserControl machst.
    Ansonsten machst Du vom Prinzip her das gleiche wie ich.
    [Enum].GetNames() gibt genauso ein System.Array zurück, wie EnumType.GetEnumValues().
    Aber die Variable b ist bei Dir vom Typ Object. Das wird zu einem Problem. Deswegen hat ErfinderDesRades auch nach Option Strict On gefragt.
    Wenn Du es so wie bei Zeile 9 bis 11 machst (Post #4, zweiter Codeausschnitt), dann bleibt das Ganze einigermaßen typensicher.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    @ErfinderDesRades
    Nein, ich hatte Option Strict ausgeschaltet. Nachdem ich das jetzt aber eingeschaltet habe, hat sich an meinem Codebeispiel nichts geändert. Woher wusstest du, dass Option Strict off war?

    Mit .GetNames gehts übrigens genauso gut:

    VB.NET-Quellcode

    1. Dim myEnum As Type = GetType(MouseSelectionRules)
    2. For Each item In [Enum].GetNames(myEnum)
    3. Dim o As New RadioButton
    4. o.Text = item
    5. FlowLayoutPanel1.Controls.Add(o)
    6. Next item


    @Niko
    Da hatte ich ein Brett vor dem Kopf, hast natürlich recht.
    Bei der Variable b, der ich zuvor den Typ Byte mal zugewiesen hatte und die jetzt item heißt, weil ich vorher nicht weiß was ankommt (byte, integer, ...), motzt Option Explicit nicht rum.

    :) Philipp

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Philipp66“ ()

    Philipp66 schrieb:

    Woher wusstest du, dass Option Strict off war?
    Zufall.;) Wenn ichs recht bedenke, isses aus deim Code doch nicht ersichtlich.

    VB.NET-Quellcode

    1. For Each b As Byte In [Enum].GetValues(GetType(MouseSelectionRules))
    sieht halt sehr komisch aus - aber ist "legal"

    Sauber wäre:

    VB.NET-Quellcode

    1. For Each b As MouseSelectionRules In [Enum].GetValues(GetType(MouseSelectionRules))

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()