La liaison de données enum propriété à un ComboBox dans WPF
Comme un exemple, le code suivant:
public enum ExampleEnum { FooBar, BarFoo }
public class ExampleClass : INotifyPropertyChanged
{
private ExampleEnum example;
public ExampleEnum ExampleProperty
{ get { return example; } { /* set and notify */; } }
}
Je veux un à databind la propriété ExampleProperty à une zone de liste déroulante, de sorte qu'il affiche les options "FooBar" et "BarFoo" et fonctionne en mode Bidirectionnel. Idéalement, je veux que mon ComboBox définition à ressembler à quelque chose comme ceci:
<ComboBox ItemsSource="What goes here?" SelectedItem="{Binding Path=ExampleProperty}" />
Actuellement, j'ai des gestionnaires pour la zone de liste déroulante.SelectionChanged et ExampleClass.PropertyChanged événements installé dans ma Fenêtre où je fais la liaison manuellement.
Est-il mieux ou une sorte de manière canonique? Souhaitez-vous généralement utiliser les Convertisseurs et comment feriez-vous pour remplir la zone de liste déroulante avec les valeurs de droite? Je ne veux pas même obtenir a commencé avec i18n droit maintenant.
Modifier
Alors une question a été répondu: Comment dois-je remplir la zone de liste déroulante avec les valeurs de droite.
Récupérer les valeurs de l'Enum comme une liste de chaînes de caractères via un ObjectDataProvider de la statique Enum.Méthode GetValues:
<Window.Resources>
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="ExampleEnumValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="ExampleEnum" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
Ce que je peux utiliser comme un ItemsSource de ma zone de liste déroulante:
<ComboBox ItemsSource="{Binding Source={StaticResource ExampleEnumValues}}"/>
- J'ai exploré, et d'une solution que vous pouvez utiliser (avec localisation) dans WPF situé à ici.
Vous devez vous connecter pour publier un commentaire.
Vous pouvez créer une extension de balisage.
Exemple d'utilisation:
En haut de votre code XAML:
et puis...
Et la mise en œuvre...
ItemsSource
param. Afin de garder la vue et le modèle découplé j'aurais besoin de créer une copie de l'énumération, dans le ViewModel et code ViewModel à la traduction entre les deux... ce Qui rendrait la solution pas que de simples plus. Ou est-il un moyen de fournir le type même du ViewModel?"EnumerationExtension” does not include a constructor that has the specified number of arguments
essayez d'utiliserItemsSource="{Binding Source={my:Enumeration EnumType={x:Type my:Status}}}"
EnumerationMember
classe pour retourner description et maintenant il fonctionne comme une balle de 7,62 mm.Dans le viewmodel, vous pouvez avoir:
Dans le code XAML de la ItemSource se lie à MyEnumTypeValues et SelectedItem se lie à SelectedMyEnumType.
Je préfère ne pas utiliser le nom d'enum dans l'INTERFACE utilisateur. Je préfère utiliser une valeur différente pour l'utilisateur (
DisplayMemberPath
) et de valeur (enum dans ce cas) (SelectedValuePath
). Ces deux valeurs peuvent être emballés àKeyValuePair
et stockés dans le dictionnaire.XAML
C#
EDIT: Compatible avec le modèle MVVM.
Enum.GetValues
, mais qui ne permettent pas de résoudre le cadre de noms à l'affiche. À la fin, et spécialement si I18n est mis en œuvre, vous devrez modifier manuellement des trucs si l'enum changements, de toute façon. Mais les énumérations ne sont pas censés changer souvent, le cas échéant, sont-ils? +1private static readonly Dictionary<ExampleEnum, string> EnumMapping = new Dictionary<ExampleEnum, string>() { {ExampleEnum.FooBar, "Foo Bar"}, {ExampleEnum.BarFoo, "Reversed Foo Bar"}, //{ExampleEnum.None, "Hidden in UI"}, }; public Dictionary<ExampleEnum, string> ExampleEnumsWithCaptions { get { return EnumMapping; } }
🙂public Dictionary<ExampleEnum, string> ExampleEnumsWithCaptions { get; } = new Dictionary<ExampleEnum, string>() { {ExampleEnum.FooBar, "Foo Bar"}, {ExampleEnum.BarFoo, "Reversed Foo Bar"}, //{ExampleEnum.None, "Hidden in UI"}, };
Je ne sais pas si c'est possible dans le code XAML seule, mais essayez ce qui suit:
Donner votre zone de liste déroulante d'un nom de sorte que vous pouvez y accéder dans le code-behind: "typesComboBox1"
Maintenant, essayez les solutions suivantes
Basé sur le acceptées, mais maintenant supprimé réponse fournie par ageektrapped j'ai créé une version allégée sans certaines des fonctionnalités les plus avancées. Tout le code est inclus ici pour vous permettre de copier-coller et de ne pas être bloqués par le lien de la pourriture.
- Je utiliser le
System.ComponentModel.DescriptionAttribute
qui est vraiment prévu pour le moment de la conception des descriptions. Si vous n'aimez pas l'aide de cet attribut, vous pouvez créer votre propre mais je pense que l'utilisation de cet attribut vraiment fait le travail. Si vous n'utilisez pas l'attribut le nom par défaut est le nom de la valeur d'enum dans le code.Ici est la classe utilisée comme source des éléments:
Vous pouvez l'utiliser dans le code XAML comme ceci:
Utilisation ObjectDataProvider:
et alors se lier à la ressource statique:
Trouver ce la solution à ce blog
Converter
pour les enum chaîne de problème.vous pouvez envisager quelque chose comme ça:
définir un style pour textblock, ou de tout autre contrôle que vous souhaitez utiliser pour afficher votre enum:
définir votre style pour ComboBoxItem
ajouter une zone de liste déroulante et de le charger avec vos valeurs enum:
si votre enum est grande, vous pouvez bien sûr faire la même chose dans le code, épargnant beaucoup de saisie.
j'aime cette approche, puisqu'il rend la localisation facile - vous pouvez définir tous les modèles une fois, et puis, vous ne mettez à jour votre chaîne fichiers de ressources.
Ma façon préférée de faire, c'est avec un
ValueConverter
de sorte que le ItemsSource et SelectedValue deux se lient à la même propriété. Cela nécessite pas de propriétés supplémentaires pour garder votre ViewModel agréable et propre.Et la définition du Convertisseur:
Ce convertisseur fonctionne avec n'importe quel protocole enum.
ValueDescription
est juste une simple classe avec unValue
de la propriété et unDescription
de la propriété. Vous pourriez tout aussi bien utiliser unTuple
avecItem1
etItem2
, ou unKeyValuePair
avecKey
etValue
au lieu de la Valeur et de Description ou de toute autre catégorie de votre choix tant qu'elle peut contenir une valeur d'énumération et de la chaîne de description de la valeur d'enum.ValueDescription
classe, leDescription
propriété peut être omis si pas nécessaire. Une classe simple avec seulementValue
propriété fonctionne aussi!.Select(e => e.ToString())
, au lieu d'utiliser leValueDescription
classe.Ici est une solution générique à l'aide d'une méthode d'aide.
Cela peut également gérer une énumération de tout type sous-jacent (byte, sbyte, uint, long, etc.)
Méthode D'Assistance:
Modèle De Vue:
Zone de liste déroulante:
Si vous utilisez un MVVM, basé sur @rudigrobler de réponse, vous pouvez effectuer les opérations suivantes:
Ajouter la propriété suivante à la ViewModel classe
Puis, dans le XAML, procédez de la manière suivante:
Essayez d'utiliser
C'est un
DevExpress
réponse spécifique basé sur le haut-voté réponse parGregor S.
(actuellement, il dispose de 128 voix).Cela signifie que nous pouvons garder le style cohérente sur l'ensemble de l'application:
Malheureusement, l'original de la réplique ne fonctionne pas avec un
ComboBoxEdit
de DevExpress sans quelques modifications.Tout d'abord, le XAML de la
ComboBoxEdit
:Needsless-à-dire, vous aurez besoin de point de
xamlExtensions
à l'espace de noms qui contient le code XAML de l'extension de la classe (qui est défini ci-dessous):Et nous avons pour point
myEnum
à l'espace de noms qui contient l'énumération:Ensuite, l'enum:
Le problème avec le code XAML est que nous ne pouvons pas utiliser
SelectedItemValue
, comme cela déclenche une erreur comme le setter est unaccessable (bits d'un oubli de votre part,DevExpress
). Donc, nous allons modifier notreViewModel
d'obtenir directement la valeur de l'objet:Pour être complet, voici le code XAML de l'extension de l'original de la réponse (un peu renommé):
Avertissement: je n'ai aucune affiliation avec DevExpress. Telerik est aussi une grande bibliothèque.
J'ai créé un open source CodePlex projet qui fait cela. Vous pouvez télécharger le package NuGet de ici.