Nehmen Sie als Beispiel den folgenden Code:
public enum ExampleEnum { FooBar, BarFoo }
public class ExampleClass : INotifyPropertyChanged
{
private ExampleEnum example;
public ExampleEnum ExampleProperty
{ get { return example; } { /* set and notify */; } }
}
Ich möchte, dass a die Eigenschaft ExampleProperty an eine ComboBox bindet, damit die Optionen "FooBar" und "BarFoo" angezeigt werden und im Modus TwoWay funktioniert. Optimalerweise soll meine ComboBox-Definition ungefähr so aussehen:
<ComboBox ItemsSource="What goes here?" SelectedItem="{Binding Path=ExampleProperty}" />
Derzeit sind in meinem Fenster Handler für die Ereignisse ComboBox.SelectionChanged und ExampleClass.PropertyChanged installiert, in denen ich die Bindung manuell durchführe.
Gibt es einen besseren oder einen kanonischen Weg? Würden Sie normalerweise Konverter verwenden und wie würden Sie die ComboBox mit den richtigen Werten füllen? Ich möchte jetzt noch nicht einmal mit i18n anfangen.
Bearbeiten
Daher wurde eine Frage beantwortet: Wie fülle ich die ComboBox mit den richtigen Werten?
Rufen Sie Enum-Werte als Liste von Zeichenfolgen über einen ObjectDataProvider von der statischen Enum.GetValues-Methode ab:
<Window.Resources>
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="ExampleEnumValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="ExampleEnum" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
Dies kann ich als ItemsSource für meine ComboBox verwenden:
<ComboBox ItemsSource="{Binding Source={StaticResource ExampleEnumValues}}"/>
Antworten:
Sie können eine benutzerdefinierte Markup-Erweiterung erstellen.
Anwendungsbeispiel:
An der Spitze Ihrer XAML:
und dann...
Und die Umsetzung ...
quelle
ItemsSource
Parameter verwenden. Um die Ansicht und das Modell entkoppelt zu halten, müsste ich eine Kopie der Aufzählung im ViewModel erstellen und ViewModel codieren, um zwischen den beiden zu übersetzen ... Was die Lösung nicht mehr so einfach machen würde. Oder gibt es eine Möglichkeit, den Typ selbst aus ViewModel bereitzustellen?Im Ansichtsmodell können Sie haben:
In XAML
ItemSource
bindet das anMyEnumTypeValues
undSelectedItem
bindet anSelectedMyEnumType
.quelle
Ich bevorzuge es, den Namen enum in der Benutzeroberfläche nicht zu verwenden. Ich bevorzuge es, einen anderen Wert für user (
DisplayMemberPath
) und einen anderen Wert für value (in diesem Fall enum) (SelectedValuePath
) zu verwenden. Diese beiden Werte können gepackt werdenKeyValuePair
in das Wörterbuch und dort gespeichert werden.XAML
C #
BEARBEITEN: Kompatibel mit dem MVVM-Muster.
quelle
Enum.GetValues
, aber das würde den Teil der anzuzeigenden Namen nicht lösen. Am Ende und insbesondere wenn I18n implementiert ist, müssen Sie die Daten manuell ändern, wenn sich die Aufzählung ändert. Aber Enums sollten sich nicht oft, wenn überhaupt, ändern, oder? +1public Dictionary<ExampleEnum, string> ExampleEnumsWithCaptions { get; } = new Dictionary<ExampleEnum, string>() { {ExampleEnum.FooBar, "Foo Bar"}, {ExampleEnum.BarFoo, "Reversed Foo Bar"}, //{ExampleEnum.None, "Hidden in UI"}, };
Ich weiß nicht, ob dies nur in XAML möglich ist, versuche aber Folgendes:
Geben Sie Ihrer ComboBox einen Namen, damit Sie im folgenden Code darauf zugreifen können: "typesComboBox1"
Versuchen Sie nun Folgendes
quelle
Basierend auf der akzeptierten, aber jetzt gelöschten Antwort von ageektrapped ich eine abgespeckte Version ohne einige der erweiterten Funktionen erstellt. Der gesamte Code ist hier enthalten, damit Sie ihn kopieren und einfügen können und nicht durch Link-Rot blockiert werden.
Ich benutze das,
System.ComponentModel.DescriptionAttribute
was wirklich für Entwurfszeitbeschreibungen gedacht ist. Wenn Sie dieses Attribut nicht mögen, können Sie Ihr eigenes erstellen, aber ich denke, dass die Verwendung dieses Attributs wirklich die Arbeit erledigt. Wenn Sie das Attribut nicht verwenden, wird standardmäßig der Name des Aufzählungswerts im Code verwendet.Hier ist die Klasse, die als Elementquelle verwendet wird:
Sie können es in XAML wie folgt verwenden:
quelle
Verwenden Sie ObjectDataProvider:
und dann an statische Ressource binden:
Diese Lösung finden Sie in diesem Blog
quelle
Converter
das Problem der Aufzählung von Zeichenfolgen machen.Meine Lieblingsmethode ist die Verwendung von a,
ValueConverter
sodass sowohl ItemsSource als auch SelectedValue an dieselbe Eigenschaft gebunden sind. Dies erfordert keine zusätzlichen Eigenschaften , um Ihr ViewModel schön und sauber zu halten.Und die Definition des Konverters:
Dieser Konverter funktioniert mit jeder Aufzählung.
ValueDescription
ist nur eine einfache Klasse mit einerValue
Eigenschaft und einerDescription
Eigenschaft. Sie können genauso gut einTuple
withItem1
undItem2
oder einKeyValuePair
withKey
andValue
anstelle von Value and Description oder eine andere Klasse Ihrer Wahl verwenden, sofern diese einen Aufzählungswert und eine Zeichenfolgenbeschreibung dieses Aufzählungswerts enthalten kann.quelle
ValueDescription
Klasse kann dieDescription
Eigenschaft weggelassen werden, wenn sie nicht benötigt wird. Eine einfache Klasse mit nurValue
Eigentum funktioniert auch!.Select(e => e.ToString())
anstatt dieValueDescription
Klasse zu verwenden.ValueDescription
auch einKeyValuePair
verwendet werden, wie hier gezeigtHier ist eine generische Lösung mit einer Hilfsmethode. Dies kann auch eine Aufzählung eines beliebigen zugrunde liegenden Typs (Byte, Sbyte, Uint, Long usw.) verarbeiten.
Hilfsmethode:
Modell anzeigen:
Kombinationsfeld:
quelle
Sie können so etwas in Betracht ziehen:
Definieren Sie einen Stil für den Textblock oder ein anderes Steuerelement, mit dem Sie Ihre Aufzählung anzeigen möchten:
Definieren Sie Ihren Stil für ComboBoxItem
Fügen Sie eine Combobox hinzu und laden Sie sie mit Ihren Enum-Werten:
Wenn Ihre Aufzählung groß ist, können Sie dies natürlich auch im Code tun, ohne viel zu tippen. Ich mag diesen Ansatz, da er die Lokalisierung vereinfacht - Sie definieren alle Vorlagen einmal und aktualisieren dann nur Ihre String-Ressourcendateien.
quelle
Wenn Sie eine MVVM verwenden, die auf der Antwort von @rudigrobler basiert, können Sie Folgendes tun:
Fügen Sie der ViewModel- Klasse die folgende Eigenschaft hinzu
Führen Sie dann in der XAML Folgendes aus:
quelle
Dies ist eine
DevExpress
spezifische Antwort, die auf der am besten bewerteten Antwort von basiertGregor S.
(derzeit hat sie 128 Stimmen).Dies bedeutet, dass wir das Styling über die gesamte Anwendung hinweg konsistent halten können:
Leider funktioniert die ursprüngliche Antwort mit einem
ComboBoxEdit
von DevExpress ohne einige Änderungen nicht.Zunächst die XAML für
ComboBoxEdit
:Unnötig zu sagen, müssen Sie zeigen
xamlExtensions
auf den Namespace zeigen, der die XAML-Erweiterungsklasse enthält (die unten definiert ist):Und wir müssen zeigen
myEnum
auf den Namespace zeigen, der die Aufzählung enthält:Dann die Aufzählung:
Das Problem mit der XAML ist, dass wir sie nicht verwenden können
SelectedItemValue
, da dies einen Fehler auslöst, da auf den Setter nicht zugegriffen werden kann (ein kleines Versehen von Ihrer SeiteDevExpress
). Also müssen wir unsere ändernViewModel
, um den Wert direkt vom Objekt zu erhalten:Der Vollständigkeit halber hier die XAML-Erweiterung aus der ursprünglichen Antwort (leicht umbenannt):
Haftungsausschluss: Ich bin nicht mit DevExpress verbunden. Telerik ist auch eine großartige Bibliothek.
quelle
Versuchen Sie es mit
quelle
Ich habe ein Open Source CodePlex- Projekt erstellt, das dies tut. Sie können das NuGet-Paket hier herunterladen .
quelle