J'aimerais que tous les objets que je lie soient définis dans mon ViewModel
J'essaie donc 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. Seulement un DataBinding, un ValueConverter réutilisable, une méthode pour obtenir une collection de descriptions pour n'importe quel type d'Enum, et une seule propriété dans le ViewModel à lier.
Lorsque je veux lier un Enum
à un ComboBox
le texte que je veux afficher ne correspond jamais aux valeurs des éléments suivants Enum
donc j'utilise le [Description()]
pour lui donner le texte que je souhaite voir apparaître dans l'écran. ComboBox
. Si j'avais un enum des jours de la semaine, il ressemblerait à quelque chose comme ceci :
public enum DayOfWeek
{
// add an optional blank value for default/no selection
[Description("")]
NOT_SET = 0,
[Description("Sunday")]
SUNDAY,
[Description("Monday")]
MONDAY,
...
}
D'abord, j'ai créé une classe d'aide avec quelques méthodes pour traiter les enums. 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 ValueConverter
. Héritant de MarkupExtension
permet de l'utiliser plus facilement dans XAML, sans avoir à 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;
}
}
Mon ViewModel
n'a besoin que d'une seule propriété que mon View
peuvent se lier à la fois pour le SelectedValue
y ItemsSource
de la combobox :
private DayOfWeek dayOfWeek;
public DayOfWeek SelectedDay
{
get { return dayOfWeek; }
set
{
if (dayOfWeek != value)
{
dayOfWeek = value;
OnPropertyChanged(nameof(SelectedDay));
}
}
}
Et enfin, pour lier le ComboBox
(en utilisant le ValueConverter
en el ItemsSource
de liaison)...
<ComboBox ItemsSource="{Binding Path=SelectedDay, Converter={x:EnumToCollectionConverter}, Mode=OneTime}"
SelectedValuePath="Value"
DisplayMemberPath="Description"
SelectedValue="{Binding Path=SelectedDay}" />
Pour mettre en œuvre cette solution, il vous suffit de copier mes EnumHelper
et EnumToCollectionConverter
classe. Ils travailleront avec tout enums. De plus, je ne l'ai pas inclus ici, mais la fonction ValueDescription
est une classe simple avec 2 propriétés d'objet publiques, l'une appelée Value
un appelé Description
. Vous pouvez le créer vous-même ou modifier le code afin d'utiliser un fichier Tuple<object, object>
o KeyValuePair<object, object>
12 votes
Voici ce que vous recherchez : WPF ObjectDataProvider - Lier une Enum à une ComboBox Vous pouvez également y télécharger le code source complet de l'exemple.
0 votes
La meilleure réponse, à mon avis, est dans : stackoverflow.com/questions/58743/
0 votes
Duplicata possible de Liaison de données d'une propriété d'énumération à une ComboBox dans WPF
0 votes
Je pense qu'une bonne méthode consiste à utiliser une EnumBindingSourceExtension et non un ObjectDataProvider. Regardez Brian Lagunas dans ce youtube. youtube.com/watch?v=Bp5LFXjwtQ0