Is it possible to use the ObjectDataProvider method to bind a ListBox to an enum, and style it somehow to display the Description attriibute? If so how would one go about doing this...?
Is it possible to use the ObjectDataProvider method to bind a ListBox to an enum, and style it somehow to display the Description attriibute? If so how would one go about doing this...?
Another solution would be a custom MarkupExtension that generates the items from enum type. This makes the xaml more compact and readable.
using System.ComponentModel;
namespace EnumDemo
{
public enum Numbers
{
[Description("1")]
One,
[Description("2")]
Two,
Three,
}
}
Example of usage:
<Window x:Class="EnumDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:EnumDemo">
<ListBox ItemsSource="{local:EnumToCollection EnumType={x:Type local:Numbers}}"/>
</Window>
MarkupExtension implementation
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows.Markup;
namespace EnumDemo
{
public class EnumToCollectionExtension : MarkupExtension
{
public Type EnumType { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (EnumType == null) throw new ArgumentNullException(nameof(EnumType));
return Enum.GetValues(EnumType).Cast<Enum>().Select(EnumToDescriptionOrString);
}
private string EnumToDescriptionOrString(Enum value)
{
return value.GetType().GetField(value.ToString())
.GetCustomAttributes(typeof(DescriptionAttribute), false)
.Cast<DescriptionAttribute>()
.FirstOrDefault()?.Description ?? value.ToString();
}
}
}
You can define a ressource file in your project (*.resx file). In this file you must define "key-value-pairs", something like this:
"YellowCars" : "Yellow Cars",
"RedCars" : "Red Cars",
and so on...
The keys are equals to your enum-entries, something like this:
public enum CarColors
{
YellowCars,
RedCars
}
and so on...
When you use WPF you can implement in your XAML-Code, something like this:
<ComboBox ItemsSource="{Binding Source={StaticResource CarColors}}" SelectedValue="{Binding CarColor, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource CarColorConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Then you must write your Converter, something like this:
using System;
using System.Globalization;
using System.Resources;
using System.Windows.Data;
public class CarColorConverter : IValueConverter
{
private static ResourceManager CarColors = new ResourceManager(typeof(Properties.CarColors));
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var key = ((Enum)value).ToString();
var result = CarColors.GetString(key);
if (result == null) {
result = key;
}
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
My answer comes 7 years to late ;-) But maybe it can be used by someone else!
Yeah, possible.
ListBox can help us do that, without converters.
The steps of this method are below:
create a ListBox and set the ItemsSource for the listbox as the enum and binding the SelectedItem of the ListBox to the selected property.
Then each ListBoxItem will be created.
public enum EnumValueNames
{
EnumValueName1,
EnumValueName2,
EnumValueName3
}
Then add below property to your DataContext (or ViewModel of MVVM), which records the selected item which is checked.
public EnumValueNames SelectedEnumValueName { get; set; }
<Window.Resources>
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type system:Enum}"
x:Key="EnumValueNames">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:EnumValueNames" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
<ListBox ItemsSource="{Binding Source={StaticResource EnumValueNames}}"
SelectedItem="{Binding SelectedEnumValueName, Mode=TwoWay}" />
References: https://www.codeproject.com/Articles/130137/Binding-TextBlock-ListBox-RadioButtons-to-Enums