Comment puis-je remplir une boîte combo WPF dans XAML avec tous les articles d'un enum donné?

dire que j'ai un enum avec quatre valeurs:

public enum CompassHeading
{
    North,
    South,
    East,
    West
}

Que faudrait-il XAML pour qu'un ComboBox soit rempli avec ces articles?

<ComboBox ItemsSource="{Binding WhatGoesHere???}" />

idéalement, je n'aurais pas à configurer le code C pour ça.

22
demandé sur ThinkingStiff 2009-02-11 21:15:12

6 réponses

vous pouvez utiliser L'ObjectDataProvider pour faire ceci:

<ObjectDataProvider MethodName="GetValues" 
    ObjectType="{x:Type sys:Enum}" x:Key="odp">
    <ObjectDataProvider.MethodParameters>
        <x:Type TypeName="local:CompassHeading"/>
    </ObjectDataProvider.MethodParameters>
</ObjectDataProvider>

<ComboBox ItemsSource="{Binding Source={StaticResource odp}}" />

j'ai trouvé la solution ici:

http://bea.stollnitz.com/blog/?p=28

23
répondu casperOne 2009-02-14 19:40:48

je pense qu'utiliser un ObjectDataProvider pour faire cela est vraiment fastidieux... J'ai une suggestion plus concise (Oui je sais, il est un peu tard...), en utilisant une extension de balisage:

<ComboBox ItemsSource="{local:EnumValues local:EmployeeType}"/>

voici le code pour l'extension du markup :

[MarkupExtensionReturnType(typeof(object[]))]
public class EnumValuesExtension : MarkupExtension
{
    public EnumValuesExtension()
    {
    }

    public EnumValuesExtension(Type enumType)
    {
        this.EnumType = enumType;
    }

    [ConstructorArgument("enumType")]
    public Type EnumType { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (this.EnumType == null)
            throw new ArgumentException("The enum type is not set");
        return Enum.GetValues(this.EnumType);
    }
}
14
répondu Thomas Levesque 2009-05-11 13:48:34

Ici est un exemple détaillé de la façon de se lier à des énumérations dans WPF

supposons que vous avez l'enum suivant

public enum EmployeeType    
{
    Manager,
    Worker
}

vous pouvez alors lier dans le codebehind

typeComboBox.ItemsSource = Enum.GetValues(typeof(EmployeeType));

ou utiliser L'ObjectDataProvider

<ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type sys:Enum}" x:Key="sysEnum">
    <ObjectDataProvider.MethodParameters>
        <x:Type TypeName="local:EmployeeType" />
    </ObjectDataProvider.MethodParameters>
</ObjectDataProvider>

et maintenant, vous pouvez lier dans le balisage

<ComboBox ItemsSource="{Binding Source={StaticResource sysEnum}}" />

également vérifier: liaison de données enum propriété à un ComboBox dans WPF

6
répondu rudigrobler 2017-05-23 12:00:17

pour une revue étape par étape des alternatives et des dérivations de la technique, essayez cette page web:

Les Disparus .NET #7: Affichage des Enums en WPF

cet article démontre une méthode pour passer outre à la présentation de certaines valeurs. Une bonne lecture avec beaucoup d'exemples de code.

3
répondu Drew Noakes 2009-02-12 15:46:44

ce peut être comme jurer dans une église, mais je voudrais déclarer chaque ComboBoxItem explicitement dans le XAML pour les raisons suivantes:

  • si j'ai besoin d'une localisation, je peux donner le XAML à un traducteur et garder le code pour moi.
  • si j'ai des valeurs enum qui ne conviennent pas à un ComboBox donné, je n'ai pas à les montrer.
  • l'ordre des énums est déterminé dans le XAML, pas nécessairement dans le code.
  • le nombre de valeurs enum à choisir n'est généralement pas très élevé. Je considérerais Enums avec des centaines de valeurs une odeur de code.
  • si j'ai besoin de graphismes ou d'autres ornements sur certains des ComboBoxItems, il serait plus facile de simplement le mettre dans XAML, où il appartient au lieu de quelque chose de Template/Trigger stuff.
  • Keep It Simple, Stupid

C # Exemple de code:

    public enum number { one, two, three };

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    private number _number = number.one;
    public number Number
    {
        get { return _number; }
        set {
            if (_number == value)
                return;
            _number = value;
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("Number"));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

code XAML:

<Window x:Class="WpfApplication6.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="480" Width="677">
<Grid>
    <ComboBox SelectedValue="{Binding Number}" SelectedValuePath="Tag">
        <ComboBoxItem Content="En" Tag="One"/>
        <ComboBoxItem Content="To" Tag="Two"/>
        <ComboBoxItem Content="Tre" Tag="Three"/>
    </ComboBox>
</Grid>

comme vous pouvez le voir, le XAML a été localisé en Norvégien, sans aucune modification du code C#.

3
répondu Guge 2010-09-03 18:09:49

une troisième solution:

c'est un peu plus de travail à l'avant, mieux est plus facile à long terme si vous êtes lié à des charges D'Énums. Utilisez un convertisseur qui prend le type d'énumération comme paramètre, et le convertit en un tableau de chaînes comme sortie.

In VB.NET:

Public Class EnumToNamesConverter
    Implements IValueConverter

    Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
        Return [Enum].GetNames(DirectCast(value, Type))
    End Function

    Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
        Throw New NotImplementedException()
    End Function
End Class

ou en C#:

public sealed class EnumToNamesConverter : IValueConverter
{
  object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    return Enum.GetNames(value.GetType());
  }

  object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
    throw New NotSupportedException()
  }
}

puis dans votre Application.xaml , ajoutez une ressource globale pour accéder à ce convertisseur:

<local:EnumToNamesConverter x:Key="EnumToNamesConverter" />

finalement utiliser le convertisseur dans n'importe quelles pages XAML où vous avez besoin des valeurs de n'importe quel Enum...

<ComboBox ItemsSource="{Binding
                        Source={x:Type local:CompassHeading},
                        Converter={StaticResource EnumToNamesConverter}}" />
1
répondu Mark 2009-08-24 19:27:28