Ich versuche ein einfaches Beispiel zu finden, in dem die Aufzählungen so angezeigt werden, wie sie sind. Alle Beispiele, die ich gesehen habe, versuchen, gut aussehende Anzeigezeichenfolgen hinzuzufügen, aber ich möchte diese Komplexität nicht.
Grundsätzlich habe ich eine Klasse, die alle Eigenschaften enthält, die ich binde, indem ich zuerst den DataContext auf diese Klasse setze und dann die Bindung wie folgt in der xaml-Datei spezifiziere:
<ComboBox ItemsSource="{Binding Path=EffectStyle}"/>
Dies zeigt jedoch nicht die Aufzählungswerte in den ComboBox
as-Elementen an.
Antworten:
Sie können dies aus Code heraus tun, indem Sie beispielsweise den folgenden Code in den Window-
Loaded
Ereignishandler einfügen :Wenn Sie es in XAML binden müssen, müssen Sie es verwenden
ObjectDataProvider
, um ein Objekt zu erstellen, das als Bindungsquelle verfügbar ist:Machen Sie auf den nächsten Code aufmerksam:
Anleitung zum Zuordnen von Namespace und Assembly, die Sie auf MSDN lesen können .
quelle
xmlns:DllAlias="clr-namespace:NamespaceInsideDll; assembly=DllAssemblyName"
und XAML hinzufügen , um ihn zu verwenden. Hier ist Leitfaden: msdn.microsoft.com/en-us/library/ms747086.aspxIch mag es, wenn alle Objekte, die ich binde, in meinem definiert werden
ViewModel
, deshalb versuche ich, die Verwendung zu vermeiden<ObjectDataProvider>
binde, in der xaml nach Möglichkeit .Meine Lösung verwendet keine in der Ansicht definierten Daten und keinen Code-Behind. Nur eine DataBinding, ein wiederverwendbarer ValueConverter, eine Methode zum Abrufen einer Sammlung von Beschreibungen für einen beliebigen Enum-Typ und eine einzelne Eigenschaft im ViewModel, an die gebunden werden soll.
Wenn ich einen
Enum
anComboBox
den Text binden möchte, den ich anzeigen möchte, stimmt er nie mit den Werten von überein. Daher verwendeEnum
ich das[Description()]
Attribut, um ihm den Text zu geben, den ich tatsächlich im Text sehen möchteComboBox
. Wenn ich eine Anzahl von Wochentagen hätte, würde es ungefähr so aussehen:Zuerst habe ich eine Hilfsklasse mit ein paar Methoden erstellt, um mit Aufzählungen umzugehen. Eine Methode erhält eine Beschreibung für einen bestimmten Wert, die andere Methode erhält alle Werte und ihre Beschreibungen für einen Typ.
Als nächstes erstellen wir eine
ValueConverter
. Das Erben vonMarkupExtension
erleichtert die Verwendung in XAML, sodass wir es nicht als Ressource deklarieren müssen.Ich
ViewModel
benötige nur 1 Eigenschaft, an die ichView
sowohl für dieSelectedValue
als auchItemsSource
für die Combobox binden kann :Und zum Schluss die
ComboBox
Ansicht binden (mit derValueConverter
in derItemsSource
Bindung) ...Um diese Lösung zu implementieren, müssen Sie nur meine
EnumHelper
Klasse undEnumToCollectionConverter
Klasse kopieren . Sie werden mit allen Aufzählungen arbeiten. Ich habe es hier auch nicht aufgenommen, aber dieValueDescription
Klasse ist nur eine einfache Klasse mit 2 öffentlichen Objekteigenschaften, eine aufgerufeneValue
, eine aufgerufeneDescription
. Sie können das selbst erstellen oder den Code ändern, um einTuple<object, object>
oder zu verwendenKeyValuePair<object, object>
quelle
ValueDescription
Klasse erstellen , die öffentliche Eigenschaften fürValue
undDescription
Tuple<T1, T2>
oder oderKeyValuePair<TKey, TValue>
anstelle derValueDescription
Klasse zu verwenden, und dann müssten Sie keinen eigenen erstellen.Ich habe eine andere Lösung mit MarkupExtension verwendet.
Ich habe eine Klasse erstellt, die die Quelle der Elemente bereitstellt:
Das ist fast alles ... Jetzt benutze es in XAML:
Ändern Sie 'enums: States' in Ihre Aufzählung
quelle
e.ToString()
für den Anzeigenamen verwenden. Sie können Ihren eigenen Übersetzer, Parser für Beschreibungsattribute, verwenden.{Binding Path=WhereEverYouWant}
), und wenn Sie möchten, dass sie die bidirektionale Bindung unterstützt, haben Sie auch ein Hintergrundfeld dafür. Sie ersetzen also nicht 2 Eigenschaften und 1 Hintergrundfeld, sondern nur 1 einzeilige schreibgeschützte Eigenschaft.Verwenden Sie ObjectDataProvider:
und dann an statische Ressource binden:
basierend auf diesem Artikel
quelle
xmlns:System="clr-namespace:System;assembly=mscorlib"
Nicks Antwort hat mir wirklich geholfen, aber ich erkannte, dass sie leicht angepasst werden konnte, um eine zusätzliche Klasse, ValueDescription, zu vermeiden. Ich erinnerte mich, dass bereits eine KeyValuePair-Klasse im Framework vorhanden ist, sodass diese stattdessen verwendet werden kann.
Der Code ändert sich nur geringfügig:
und schließlich die XAML:
Ich hoffe das ist hilfreich für andere.
quelle
KeyValuePair
aber am Ende entschied ich mich, aKeyValuePair
zu verwenden, um etwas darzustellen, das kein Schlüssel-Wert-Paar ist, nur um zu vermeiden, dass eine trivial einfache Klasse geschrieben wird, was nicht viel Sinn machte. DieValueDescription
Klasse besteht nur aus 5 Zeilen, und 2 davon sind nur{
und}
Sie müssen ein Array der Werte in der Aufzählung erstellen, das erstellt werden kann, indem Sie System.Enum.GetValues () aufrufen und das übergeben
Type
die Aufzählung übergeben wird, deren Elemente Sie möchten.Wenn Sie dies für die
ItemsSource
Eigenschaft angeben , sollte sie mit allen Werten der Aufzählung gefüllt sein. Sie wollen wahrscheinlich bindenSelectedItem
anEffectStyle
(vorausgesetzt , es ist eine Eigenschaft des gleichen Enum ist, und enthält den aktuellen Wert).quelle
Alle oben genannten Beiträge haben einen einfachen Trick verpasst. Anhand der Bindung von SelectedValue können Sie herausfinden, wie die ItemsSource AUTOMAGISCH gefüllt wird, sodass Ihr XAML-Markup gerecht ist.
Zum Beispiel in meinem ViewModel habe ich
ValidateRaiseAndSetIfChanged ist mein INPC-Hook. Ihre können abweichen.
Die Implementierung von EnumComboBox ist wie folgt, aber zuerst brauche ich einen kleinen Helfer, um meine Aufzählungszeichenfolgen und -werte abzurufen
und die Hauptklasse (Hinweis: Ich verwende ReactiveUI, um Eigenschaftsänderungen über WhenAny zu verknüpfen.)
Sie müssen den Stil auch in Generic.XAML richtig einstellen, sonst rendert Ihre Box nichts und Sie ziehen sich die Haare aus.
und das ist das Dies könnte natürlich erweitert werden, um i18n zu unterstützen, würde aber den Beitrag verlängern.
quelle
Universelle Apps scheinen etwas anders zu funktionieren. Es verfügt nicht über die volle Leistung von XAML mit vollem Funktionsumfang. Was für mich funktioniert hat ist:
Nur zum Spaß habe ich eine kleine Klasse mit Vorlagen zusammengestellt, um dies zu unterstützen, und sie auf den MSDN-Beispielseiten veröffentlicht . Mit den zusätzlichen Bits kann ich optional die Namen der Aufzählungen überschreiben und einige der Aufzählungen ausblenden. Mein Code sieht schrecklich aus wie der von Nick (oben), den ich gerne früher gesehen hätte.
quelle
Es gibt viele ausgezeichnete Antworten auf diese Frage und ich reiche meine demütig ein. Ich finde, dass meine etwas einfacher und eleganter ist. Es ist nur ein Wertekonverter erforderlich.
Angesichts einer Aufzählung ...
und ein Wertekonverter ...
Ressourcen...
XAML-Deklaration ...
Modell anzeigen ...
Resultierende Combobox ...
quelle
Sie sollten die Antwort von Rogers und Greg mit einem solchen Enum-Wertkonverter erweitern, wenn Sie direkt an die Eigenschaften des Enum-Objektmodells binden.
quelle
Wenn Sie an eine tatsächliche Enum-Eigenschaft in Ihrem ViewModel binden und nicht an eine int-Darstellung einer Enum, wird es schwierig. Ich fand es notwendig, an die Zeichenfolgendarstellung zu binden, NICHT an den int-Wert, wie in allen obigen Beispielen erwartet.
Sie können feststellen, ob dies der Fall ist, indem Sie ein einfaches Textfeld an die Eigenschaft binden, an die Sie in Ihrem ViewModel binden möchten. Wenn Text angezeigt wird, binden Sie ihn an die Zeichenfolge. Wenn eine Zahl angezeigt wird, binden Sie an den Wert. Hinweis Ich habe Display zweimal verwendet, was normalerweise ein Fehler wäre, aber es ist die einzige Möglichkeit, wie es funktioniert.
Greg
quelle
Ich mochte die Antwort von tom.maruska , aber ich musste jeden Aufzählungstyp unterstützen, auf den meine Vorlage zur Laufzeit stoßen könnte. Dafür musste ich eine Bindung verwenden, um den Typ für die Markup-Erweiterung anzugeben. Ich konnte in dieser Antwort von nicolay.anykienko eine sehr flexible Markup-Erweiterung entwickeln, die auf jeden Fall funktionieren würde, was mir einfällt. Es wird so konsumiert:
Die Quelle für die oben genannte Mashed-Up-Markup-Erweiterung:
quelle
Einfache und klare Erklärung: http://brianlagunas.com/a-better-way-to-data-bind-enums-in-wpf/
...
...
quelle
Mit
ReactiveUI
habe ich die folgende alternative Lösung erstellt. Es ist keine elegante All-in-One-Lösung, aber ich denke zumindest, dass sie lesbar ist.In meinem Fall ist das Binden einer Liste
enum
an ein Steuerelement ein seltener Fall, sodass ich die Lösung nicht über die Codebasis skalieren muss. Der Code kann jedoch durch ÄndernEffectStyleLookup.Item
in einen Code allgemeiner gestaltet werdenObject
. Ich habe es mit meinem Code getestet, es sind keine weiteren Änderungen erforderlich. Dies bedeutet, dass die eine Hilfsklasse auf jedeenum
Liste angewendet werden kann . Das würde zwar die Lesbarkeit beeinträchtigen -ReactiveList<EnumLookupHelper>
hat aber keinen großen Klang.Verwenden der folgenden Hilfsklasse:
Konvertieren Sie im ViewModel die Liste der Aufzählungen und machen Sie sie als Eigenschaft verfügbar:
In der
ComboBox
, nutzen dieSelectedValuePath
Eigenschaft, auf dem Original zu bindenenum
Wert:In der Ansicht können wir das Original
enum
an dasSelectedEffectStyle
im ViewModel binden , aber denToString()
Wert in folgendem anzeigenComboBox
:quelle
Ich füge meinen Kommentar hinzu (in VB leider, aber das Konzept kann sofort auf C # repliziert werden), weil ich nur darauf verweisen musste und keine der Antworten mochte, da sie zu komplex waren. Es sollte nicht so schwierig sein.
Also habe ich mir einen einfacheren Weg ausgedacht. Binden Sie die Enumeratoren an ein Wörterbuch. Binden Sie das Wörterbuch an die Combobox.
Meine Combobox:
Mein Code-Behind. Hoffentlich hilft das jemand anderem.
quelle
Nicks Lösung kann noch weiter vereinfacht werden, ohne dass Sie etwas Besonderes benötigen. Sie würden nur einen einzigen Konverter benötigen:
Sie verwenden dies dann überall dort, wo Ihr Kombinationsfeld angezeigt werden soll:
quelle
Ich würde nicht empfehlen, dies so zu implementieren, wie es ist, aber hoffentlich kann dies eine gute Lösung inspirieren.
Angenommen, Ihre Aufzählung lautet Foo. Dann können Sie so etwas tun.
Anschließend können Sie bei der
Window.Load
Methode alle Aufzählungen in eine laden,ObservableCollection<FooViewModel>
die Sie als DataContext der Combobox festlegen können.quelle
Ich habe es einfach gehalten. Ich habe eine Liste von Elementen mit den Aufzählungswerten in meinem ViewModel erstellt:
In meinem XAML-Code brauche ich nur Folgendes:
quelle