J'essaie de trouver un exemple simple où les énumérations sont affichées telles quelles. Tous les exemples que j'ai vus essaient d'ajouter de jolies chaînes d'affichage, mais je ne veux pas de cette complexité.
Fondamentalement, j'ai une classe qui contient toutes les propriétés que je lie, en définissant d'abord le DataContext sur cette classe, puis en spécifiant la liaison comme celle-ci dans le fichier xaml:
<ComboBox ItemsSource="{Binding Path=EffectStyle}"/>
Mais cela ne montre pas les valeurs d'énumération dans les ComboBox
éléments as.
Réponses:
Vous pouvez le faire à partir du code en plaçant le code suivant dans le
Loaded
gestionnaire d'événements Window , par exemple:yourComboBox.ItemsSource = Enum.GetValues(typeof(EffectStyle)).Cast<EffectStyle>();
Si vous avez besoin de le lier en XAML, vous devez utiliser
ObjectDataProvider
pour créer un objet disponible comme source de liaison:<Window x:Class="YourNamespace.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:System="clr-namespace:System;assembly=mscorlib" xmlns:StyleAlias="clr-namespace:Motion.VideoEffects"> <Window.Resources> <ObjectDataProvider x:Key="dataFromEnum" MethodName="GetValues" ObjectType="{x:Type System:Enum}"> <ObjectDataProvider.MethodParameters> <x:Type TypeName="StyleAlias:EffectStyle"/> </ObjectDataProvider.MethodParameters> </ObjectDataProvider> </Window.Resources> <Grid> <ComboBox ItemsSource="{Binding Source={StaticResource dataFromEnum}}" SelectedItem="{Binding Path=CurrentEffectStyle}" /> </Grid> </Window>
Attirez l'attention sur le code suivant:
xmlns:System="clr-namespace:System;assembly=mscorlib" xmlns:StyleAlias="clr-namespace:Motion.VideoEffects"
Guidez comment mapper l'espace de noms et l'assembly que vous pouvez lire sur MSDN .
la source
xmlns:DllAlias="clr-namespace:NamespaceInsideDll; assembly=DllAssemblyName"
du XAML pour l'utiliser. Voici le guide: msdn.microsoft.com/en-us/library/ms747086.aspxJ'aime que tous les objets que je lie soient définis dans my
ViewModel
, donc j'essaie d'éviter d'utiliser<ObjectDataProvider>
dans le xaml lorsque cela est possible.Ma solution n'utilise aucune donnée définie dans la vue et aucun code-behind. Uniquement un DataBinding, un ValueConverter réutilisable, une méthode pour obtenir une collection de descriptions pour tout type Enum et une seule propriété dans le ViewModel à laquelle se lier.
Lorsque je veux lier un
Enum
à un,ComboBox
le texte que je veux afficher ne correspond jamais aux valeurs deEnum
, donc j'utilise l'[Description()]
attribut pour lui donner le texte que je veux réellement voir dans leComboBox
. Si j'avais une énumération des jours de la semaine, cela ressemblerait à ceci:public enum DayOfWeek { // add an optional blank value for default/no selection [Description("")] NOT_SET = 0, [Description("Sunday")] SUNDAY, [Description("Monday")] MONDAY, ... }
J'ai d'abord créé une classe d'assistance avec quelques méthodes pour gérer les énumérations. Une méthode obtient une description pour une valeur spécifique, l'autre méthode obtient toutes les valeurs et leurs descriptions pour un type.
public static class EnumHelper { public static string Description(this Enum value) { var attributes = value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false); if (attributes.Any()) return (attributes.First() as DescriptionAttribute).Description; // If no description is found, the least we can do is replace underscores with spaces // You can add your own custom default formatting logic here TextInfo ti = CultureInfo.CurrentCulture.TextInfo; return ti.ToTitleCase(ti.ToLower(value.ToString().Replace("_", " "))); } public static IEnumerable<ValueDescription> GetAllValuesAndDescriptions(Type t) { if (!t.IsEnum) throw new ArgumentException($"{nameof(t)} must be an enum type"); return Enum.GetValues(t).Cast<Enum>().Select((e) => new ValueDescription() { Value = e, Description = e.Description() }).ToList(); } }
Ensuite, nous créons un fichier
ValueConverter
. L'héritage deMarkupExtension
facilite son utilisation en XAML, nous n'avons donc pas à le déclarer en tant que ressource.[ValueConversion(typeof(Enum), typeof(IEnumerable<ValueDescription>))] public class EnumToCollectionConverter : MarkupExtension, IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return EnumHelper.GetAllValuesAndDescriptions(value.GetType()); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return null; } public override object ProvideValue(IServiceProvider serviceProvider) { return this; } }
My
ViewModel
n'a besoin que d'une propriété à laquelle myView
peut se lier à la fois pour leSelectedValue
etItemsSource
de la zone de liste déroulante:private DayOfWeek dayOfWeek; public DayOfWeek SelectedDay { get { return dayOfWeek; } set { if (dayOfWeek != value) { dayOfWeek = value; OnPropertyChanged(nameof(SelectedDay)); } } }
Et enfin pour lier la
ComboBox
vue (en utilisant leValueConverter
dans laItemsSource
liaison) ...<ComboBox ItemsSource="{Binding Path=SelectedDay, Converter={x:EnumToCollectionConverter}, Mode=OneTime}" SelectedValuePath="Value" DisplayMemberPath="Description" SelectedValue="{Binding Path=SelectedDay}" />
Pour implémenter cette solution, il vous suffit de copier ma
EnumHelper
classe et maEnumToCollectionConverter
classe. Ils fonctionneront avec toutes les énumérations. De plus, je ne l'ai pas inclus ici, mais laValueDescription
classe est juste une classe simple avec 2 propriétés d'objet public, une appeléeValue
, une appeléeDescription
. Vous pouvez le créer vous-même ou modifier le code pour utiliser unTuple<object, object>
ouKeyValuePair<object, object>
la source
ValueDescription
classe qui a des propriétés publiques pourValue
etDescription
Tuple<T1, T2>
ou ouKeyValuePair<TKey, TValue>
au lieu de laValueDescription
classe et vous n'aurez pas à créer le vôtre.J'ai utilisé une autre solution utilisant MarkupExtension.
J'ai créé une classe qui fournit la source des éléments:
public class EnumToItemsSource : MarkupExtension { private readonly Type _type; public EnumToItemsSource(Type type) { _type = type; } public override object ProvideValue(IServiceProvider serviceProvider) { return Enum.GetValues(_type) .Cast<object>() .Select(e => new { Value = (int)e, DisplayName = e.ToString() }); } }
C'est presque tout ... Maintenant, utilisez-le en XAML:
<ComboBox DisplayMemberPath="DisplayName" ItemsSource="{persons:EnumToItemsSource {x:Type enums:States}}" SelectedValue="{Binding Path=WhereEverYouWant}" SelectedValuePath="Value" />
Remplacez «enums: States» par votre enum
la source
e.ToString()
pour le nom d'affichage. Vous pouvez utiliser votre propre traducteur, analyseur d'attributs de description, peu importe.{Binding Path=WhereEverYouWant}
) et si vous voulez qu'elle prenne en charge la liaison bidirectionnelle, vous aurez également un champ de sauvegarde pour elle. Ainsi, vous ne remplacez pas 2 propriétés et 1 champ de sauvegarde en faisant cela, vous ne remplacez qu'une seule propriété en lecture seule sur une seule ligne.Utilisez ObjectDataProvider:
<ObjectDataProvider x:Key="enumValues" MethodName="GetValues" ObjectType="{x:Type System:Enum}"> <ObjectDataProvider.MethodParameters> <x:Type TypeName="local:ExampleEnum"/> </ObjectDataProvider.MethodParameters> </ObjectDataProvider>
puis liez à la ressource statique:
ItemsSource="{Binding Source={StaticResource enumValues}}"
basé sur cet article
la source
xmlns:System="clr-namespace:System;assembly=mscorlib"
La réponse de Nick m'a vraiment aidé, mais j'ai réalisé qu'elle pouvait être légèrement modifiée, pour éviter une classe supplémentaire, ValueDescription. Je me suis souvenu qu'il existe déjà une classe KeyValuePair dans le framework, donc cela peut être utilisé à la place.
Le code ne change que légèrement:
public static IEnumerable<KeyValuePair<string, string>> GetAllValuesAndDescriptions<TEnum>() where TEnum : struct, IConvertible, IComparable, IFormattable { if (!typeof(TEnum).IsEnum) { throw new ArgumentException("TEnum must be an Enumeration type"); } return from e in Enum.GetValues(typeof(TEnum)).Cast<Enum>() select new KeyValuePair<string, string>(e.ToString(), e.Description()); } public IEnumerable<KeyValuePair<string, string>> PlayerClassList { get { return EnumHelper.GetAllValuesAndDescriptions<PlayerClass>(); } }
et enfin le XAML:
<ComboBox ItemSource="{Binding Path=PlayerClassList}" DisplayMemberPath="Value" SelectedValuePath="Key" SelectedValue="{Binding Path=SelectedClass}" />
J'espère que cela sera utile aux autres.
la source
KeyValuePair
mais à la fin j'ai décidé d'utiliser aKeyValuePair
pour représenter quelque chose qui n'est pas une paire clé-valeur juste pour éviter d'écrire une classe trivialement simple n'avait pas beaucoup de sens. LaValueDescription
classe ne compte que 5 lignes, et 2 d'entre elles sont justes{
et}
Vous devrez créer un tableau des valeurs de l'énumération, qui peut être créé en appelant System.Enum.GetValues () , en lui passant
Type
l'énumération dont vous voulez les éléments.Si vous spécifiez ceci pour la
ItemsSource
propriété, elle doit être remplie avec toutes les valeurs de l'énumération. Vous souhaitez probablement établir une liaisonSelectedItem
avecEffectStyle
(en supposant qu'il s'agit d'une propriété de la même énumération et qu'il contienne la valeur actuelle).la source
Tous les messages ci-dessus ont manqué une astuce simple. Il est possible à partir de la liaison de SelectedValue de savoir comment remplir le ItemsSource AUTOMAGIQUEMENT afin que votre balisage XAML soit juste.
<Controls:EnumComboBox SelectedValue="{Binding Fool}"/>
Par exemple dans mon ViewModel j'ai
public enum FoolEnum { AAA, BBB, CCC, DDD }; FoolEnum _Fool; public FoolEnum Fool { get { return _Fool; } set { ValidateRaiseAndSetIfChanged(ref _Fool, value); } }
ValidateRaiseAndSetIfChanged est mon hook INPC. Le vôtre peut différer.
L'implémentation d'EnumComboBox est la suivante, mais j'aurai d'abord besoin d'un petit assistant pour obtenir mes chaînes d'énumération et mes valeurs
public static List<Tuple<object, string, int>> EnumToList(Type t) { return Enum .GetValues(t) .Cast<object>() .Select(x=>Tuple.Create(x, x.ToString(), (int)x)) .ToList(); }
et la classe principale (notez que j'utilise ReactiveUI pour accrocher les changements de propriété via WhenAny)
using ReactiveUI; using ReactiveUI.Utils; using System; using System.Collections.Generic; using System.Linq; using System.Reactive.Linq; using System.Windows; using System.Windows.Documents; namespace My.Controls { public class EnumComboBox : System.Windows.Controls.ComboBox { static EnumComboBox() { DefaultStyleKeyProperty.OverrideMetadata(typeof(EnumComboBox), new FrameworkPropertyMetadata(typeof(EnumComboBox))); } protected override void OnInitialized( EventArgs e ) { base.OnInitialized(e); this.WhenAnyValue(p => p.SelectedValue) .Where(p => p != null) .Select(o => o.GetType()) .Where(t => t.IsEnum) .DistinctUntilChanged() .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(FillItems); } private void FillItems(Type enumType) { List<KeyValuePair<object, string>> values = new List<KeyValuePair<object,string>>(); foreach (var idx in EnumUtils.EnumToList(enumType)) { values.Add(new KeyValuePair<object, string>(idx.Item1, idx.Item2)); } this.ItemsSource = values.Select(o=>o.Key.ToString()).ToList(); UpdateLayout(); this.ItemsSource = values; this.DisplayMemberPath = "Value"; this.SelectedValuePath = "Key"; } } }
Vous devez également définir correctement le style dans Generic.XAML ou votre boîte ne rendra rien et vous vous tirerez les cheveux.
<Style TargetType="{x:Type local:EnumComboBox}" BasedOn="{StaticResource {x:Type ComboBox}}"> </Style>
et c'est ça. Cela pourrait évidemment être étendu pour prendre en charge i18n mais allongerait le poste.
la source
Les applications universelles semblent fonctionner un peu différemment; il n'a pas toute la puissance du XAML complet. Ce qui a fonctionné pour moi, c'est:
Juste pour le plaisir, j'ai créé une petite classe basée sur des modèles pour vous aider et je l'ai publiée sur les pages MSDN Samples . Les bits supplémentaires me permettent éventuellement de remplacer les noms des énumérations et de masquer certaines des énumérations. Mon code ressemble à celui de Nick (ci-dessus), que j'aurais aimé voir plus tôt.
la source
Il existe de nombreuses excellentes réponses à cette question et je soumets humblement la mienne. Je trouve que le mien est un peu plus simple et plus élégant. Il ne nécessite qu'un convertisseur de valeur.
Étant donné une énumération ...
public enum ImageFormat { [Description("Windows Bitmap")] BMP, [Description("Graphics Interchange Format")] GIF, [Description("Joint Photographic Experts Group Format")] JPG, [Description("Portable Network Graphics Format")] PNG, [Description("Tagged Image Format")] TIFF, [Description("Windows Media Photo Format")] WDP }
et un convertisseur de valeur ...
public class ImageFormatValueConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is ImageFormat format) { return GetString(format); } return null; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { if (value is string s) { return Enum.Parse(typeof(ImageFormat), s.Substring(0, s.IndexOf(':'))); } return null; } public string[] Strings => GetStrings(); public static string GetString(ImageFormat format) { return format.ToString() + ": " + GetDescription(format); } public static string GetDescription(ImageFormat format) { return format.GetType().GetMember(format.ToString())[0].GetCustomAttribute<DescriptionAttribute>().Description; } public static string[] GetStrings() { List<string> list = new List<string>(); foreach (ImageFormat format in Enum.GetValues(typeof(ImageFormat))) { list.Add(GetString(format)); } return list.ToArray(); } }
Ressources...
<local:ImageFormatValueConverter x:Key="ImageFormatValueConverter"/>
Déclaration XAML ...
<ComboBox Grid.Row="9" ItemsSource="{Binding Source={StaticResource ImageFormatValueConverter}, Path=Strings}" SelectedItem="{Binding Format, Converter={StaticResource ImageFormatValueConverter}}"/>
Voir le modèle ...
private ImageFormat _imageFormat = ImageFormat.JPG; public ImageFormat Format { get => _imageFormat; set { if (_imageFormat != value) { _imageFormat = value; OnPropertyChanged(); } } }
Combobox résultante ...
la source
public class EnumItemsConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (!value.GetType().IsEnum) return false; var enumName = value.GetType(); var obj = Enum.Parse(enumName, value.ToString()); return System.Convert.ToInt32(obj); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return Enum.ToObject(targetType, System.Convert.ToInt32(value)); } }
Vous devriez étendre la réponse de Rogers et Greg avec un tel type de convertisseur de valeur Enum, si vous liez directement aux propriétés du modèle objet enum.
la source
Si vous liez à une propriété enum réelle sur votre ViewModel, et non à une représentation int d'un enum, les choses se compliquent. J'ai trouvé qu'il était nécessaire de se lier à la représentation sous forme de chaîne, PAS à la valeur int comme prévu dans tous les exemples ci-dessus.
Vous pouvez savoir si c'est le cas en liant une simple zone de texte à la propriété à laquelle vous souhaitez vous lier sur votre ViewModel. S'il affiche du texte, liez à la chaîne. S'il affiche un nombre, liez à la valeur. Remarque J'ai utilisé Display deux fois, ce qui serait normalement une erreur, mais c'est la seule façon dont cela fonctionne.
<ComboBox SelectedValue="{Binding ElementMap.EdiDataType, Mode=TwoWay}" DisplayMemberPath="Display" SelectedValuePath="Display" ItemsSource="{Binding Source={core:EnumToItemsSource {x:Type edi:EdiDataType}}}" />
Greg
la source
J'ai aimé la réponse de tom.maruska , mais je devais prendre en charge tout type d'énumération que mon modèle pourrait rencontrer au moment de l'exécution. Pour cela, j'ai dû utiliser une liaison pour spécifier le type de l'extension de balisage. J'ai pu travailler dans cette réponse de nicolay.anykienko pour proposer une extension de balisage très flexible qui fonctionnerait dans tous les cas auxquels je pense. Il se consomme comme ceci:
<ComboBox SelectedValue="{Binding MyEnumProperty}" SelectedValuePath="Value" ItemsSource="{local:EnumToObjectArray SourceEnum={Binding MyEnumProperty}}" DisplayMemberPath="DisplayName" />
La source de l'extension de balisage écrasée référencée ci-dessus:
class EnumToObjectArray : MarkupExtension { public BindingBase SourceEnum { get; set; } public override object ProvideValue(IServiceProvider serviceProvider) { IProvideValueTarget target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; DependencyObject targetObject; DependencyProperty targetProperty; if (target != null && target.TargetObject is DependencyObject && target.TargetProperty is DependencyProperty) { targetObject = (DependencyObject)target.TargetObject; targetProperty = (DependencyProperty)target.TargetProperty; } else { return this; } BindingOperations.SetBinding(targetObject, EnumToObjectArray.SourceEnumBindingSinkProperty, SourceEnum); var type = targetObject.GetValue(SourceEnumBindingSinkProperty).GetType(); if (type.BaseType != typeof(System.Enum)) return this; return Enum.GetValues(type) .Cast<Enum>() .Select(e => new { Value=e, Name = e.ToString(), DisplayName = Description(e) }); } private static DependencyProperty SourceEnumBindingSinkProperty = DependencyProperty.RegisterAttached("SourceEnumBindingSink", typeof(Enum) , typeof(EnumToObjectArray), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits)); /// <summary> /// Extension method which returns the string specified in the Description attribute, if any. Oherwise, name is returned. /// </summary> /// <param name="value">The enum value.</param> /// <returns></returns> public static string Description(Enum value) { var attrs = value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false); if (attrs.Any()) return (attrs.First() as DescriptionAttribute).Description; //Fallback return value.ToString().Replace("_", " "); } }
la source
Explication simple et claire: http://brianlagunas.com/a-better-way-to-data-bind-enums-in-wpf/
xmlns:local="clr-namespace:BindingEnums" xmlns:sys="clr-namespace:System;assembly=mscorlib"
...
<Window.Resources> <ObjectDataProvider x:Key="dataFromEnum" MethodName="GetValues" ObjectType="{x:Type sys:Enum}"> <ObjectDataProvider.MethodParameters> <x:Type TypeName="local:Status"/> </ObjectDataProvider.MethodParameters> </ObjectDataProvider> </Window.Resources>
...
<Grid> <ComboBox HorizontalAlignment="Center" VerticalAlignment="Center" MinWidth="150" ItemsSource="{Binding Source={StaticResource dataFromEnum}}"/> </Grid>
la source
En utilisant
ReactiveUI
, j'ai créé la solution alternative suivante. Ce n'est pas une solution tout-en-un élégante, mais je pense qu'elle est à tout le moins lisible.Dans mon cas, la liaison d'une liste de
enum
à un contrôle est un cas rare, je n'ai donc pas besoin de mettre à l'échelle la solution sur la base de code. Cependant, le code peut être plus générique en changeantEffectStyleLookup.Item
en unObject
. Je l'ai testé avec mon code, aucune autre modification n'est nécessaire. Ce qui signifie que la seule classe d'assistance peut être appliquée à n'importe quelleenum
liste. Bien que cela réduirait sa lisibilité -ReactiveList<EnumLookupHelper>
n'a pas beaucoup de sens.Utilisation de la classe d'assistance suivante:
public class EffectStyleLookup { public EffectStyle Item { get; set; } public string Display { get; set; } }
Dans le ViewModel, convertissez la liste des énumérations et exposez-la en tant que propriété:
public ViewModel : ReactiveObject { private ReactiveList<EffectStyleLookup> _effectStyles; public ReactiveList<EffectStyleLookup> EffectStyles { get { return _effectStyles; } set { this.RaiseAndSetIfChanged(ref _effectStyles, value); } } // See below for more on this private EffectStyle _selectedEffectStyle; public EffectStyle SelectedEffectStyle { get { return _selectedEffectStyle; } set { this.RaiseAndSetIfChanged(ref _selectedEffectStyle, value); } } public ViewModel() { // Convert a list of enums into a ReactiveList var list = (IList<EffectStyle>)Enum.GetValues(typeof(EffectStyle)) .Select( x => new EffectStyleLookup() { Item = x, Display = x.ToString() }); EffectStyles = new ReactiveList<EffectStyle>( list ); } }
Dans le
ComboBox
, utilisez laSelectedValuePath
propriété pour vous lier à laenum
valeur d' origine :<ComboBox Name="EffectStyle" DisplayMemberPath="Display" SelectedValuePath="Item" />
Dans la vue, cela nous permet de lier l'original
enum
àSelectedEffectStyle
dans le ViewModel, mais d'afficher laToString()
valeur dans leComboBox
:this.WhenActivated( d => { d( this.OneWayBind(ViewModel, vm => vm.EffectStyles, v => v.EffectStyle.ItemsSource) ); d( this.Bind(ViewModel, vm => vm.SelectedEffectStyle, v => v.EffectStyle.SelectedValue) ); });
la source
J'ajoute mon commentaire (en VB, malheureusement, mais le concept peut être facilement reproduit en C # en un clin d'œil), car je devais simplement faire référence à cela et n'aimais aucune des réponses car elles étaient trop complexes. Cela ne devrait pas être aussi difficile.
Alors j'ai trouvé un moyen plus simple. Liez les énumérateurs à un dictionnaire. Liez ce dictionnaire au Combobox.
Ma combobox:
<ComboBox x:Name="cmbRole" VerticalAlignment="Stretch" IsEditable="False" Padding="2" Margin="0" FontSize="11" HorizontalAlignment="Stretch" TabIndex="104" SelectedValuePath="Key" DisplayMemberPath="Value" />
Mon code derrière. Espérons que cela aide quelqu'un d'autre.
Dim tDict As New Dictionary(Of Integer, String) Dim types = [Enum].GetValues(GetType(Helper.Enumerators.AllowedType)) For Each x As Helper.Enumerators.AllowedType In types Dim z = x.ToString() Dim y = CInt(x) tDict.Add(y, z) Next cmbRole.ClearValue(ItemsControl.ItemsSourceProperty) cmbRole.ItemsSource = tDict
la source
La solution de Nick peut être simplifiée davantage, sans rien d'extraordinaire, vous n'auriez besoin que d'un seul convertisseur:
[ValueConversion(typeof(Enum), typeof(IEnumerable<Enum>))] public class EnumToCollectionConverter : MarkupExtension, IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var r = Enum.GetValues(value.GetType()); return r; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return null; } public override object ProvideValue(IServiceProvider serviceProvider) { return this; } }
Vous utilisez ensuite ceci partout où vous voulez que votre combo apparaisse:
<ComboBox ItemsSource="{Binding PagePosition, Converter={converter:EnumToCollectionConverter}, Mode=OneTime}" SelectedItem="{Binding PagePosition}" />
la source
Je ne recommanderais pas de mettre en œuvre cela tel quel, mais j'espère que cela peut inspirer une bonne solution.
Disons que votre énumération est Foo. Ensuite, vous pouvez faire quelque chose comme ça.
public class FooViewModel : ViewModel { private int _fooValue; public int FooValue { get => _fooValue; set { _fooValue = value; OnPropertyChange(); OnPropertyChange(nameof(Foo)); OnPropertyChange(nameof(FooName)); } } public Foo Foo { get => (Foo)FooValue; set { _fooValue = (int)value; OnPropertyChange(); OnPropertyChange(nameof(FooValue)); OnPropertyChange(nameof(FooName)); } } public string FooName { get => Enum.GetName(typeof(Foo), Foo); } public FooViewModel(Foo foo) { Foo = foo; } }
Ensuite, sur la
Window.Load
méthode, vous pouvez charger toutes les énumérations dans unObservableCollection<FooViewModel>
que vous pouvez définir comme DataContext de la zone de liste déroulante.la source
Je suis juste resté simple. J'ai créé une liste d'éléments avec les valeurs d'énumération dans mon ViewModel:
public enum InputsOutputsBoth { Inputs, Outputs, Both } private IList<InputsOutputsBoth> _ioTypes = new List<InputsOutputsBoth>() { InputsOutputsBoth.Both, InputsOutputsBoth.Inputs, InputsOutputsBoth.Outputs }; public IEnumerable<InputsOutputsBoth> IoTypes { get { return _ioTypes; } set { } } private InputsOutputsBoth _selectedIoType; public InputsOutputsBoth SelectedIoType { get { return _selectedIoType; } set { _selectedIoType = value; OnPropertyChanged("SelectedIoType"); OnSelectionChanged(); } }
Dans mon code xaml, j'ai juste besoin de ceci:
<ComboBox ItemsSource="{Binding IoTypes}" SelectedItem="{Binding SelectedIoType, Mode=TwoWay}">
la source