Повесить enum на элемент combobox

229
19 мая 2018, 13:00

Есть VM со свойством типа enum.

Как вывести в ComboBox все значения из перечисления, так что бы выбранный элемент в ComboBox обновлял значение во ViewModel?

Answer 1

Допустим, у меня есть такой enum Этап:

enum Stage
{
    First, Second, Third, Fourth
}

и в VM свойство такого типа:

Stage stage;
public Stage Stage
{
    get => stage;
    set => Set(ref stage, value);
}

В представлении я могу привязать текущий элемент ComboBoxа к этому свойству:

<ComboBox SelectedItem="{Binding Stage}"
          ItemsSource="..."/>

остается как-то получить список всех значений Enum чтобы привязать их в ItemsSource. Я предлагаю сделать для этого небольшое расширение разметки:

class EnumExtension : MarkupExtension
{
    public Type EnumType { get; set; }
    public EnumExtension() { }
    public EnumExtension(Type enumType) => EnumType = enumType;
    public override object ProvideValue(IServiceProvider serviceProvider)
        => Enum.GetValues(EnumType);
}

Воспользуемся им:

ItemsSource="{c:Enum EnumType=c:Stage}"

или, благодаря наличию конструктора с параметром, еще короче:

ItemsSource="{c:Enum c:Stage}"

В принципе это уже работает, но в выпадающем списке выводятся строки First, Second и т.д., хочется привести их в нормальный человеческий вид.

Сделаем это с помощью конвертера:

class EnumToDescriptionConverter : IValueConverter
{
    public IDictionary Dict { get; set; }
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var key = value?.ToString();
        return Dict.Contains(key) ? Dict[key] : null;
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Dict.Cast<DictionaryEntry>().FirstOrDefault(p => p.Value == value).Key;
    }
}

В этот конвертер через свойство можно внедрить нужный словарь, например, в зависимости от текущего языка.

Ну и немного модифицируем EnumExtension, чтобы также использовался конвертер:

class EnumExtension : MarkupExtension
{
    public IValueConverter Converter { get; set; }
    public Type EnumType { get; set; }
    public EnumExtension() { }
    public EnumExtension(Type enumType) => EnumType = enumType;
    public override object ProvideValue(IServiceProvider serviceProvider)
        => Enum.GetValues(EnumType).Cast<ValueType>()
               .Select(t => Converter?.Convert(t, EnumType, null, Thread.CurrentThread.CurrentUICulture) ?? t);
}

Остается только завести в ресурсах словарь, который будет сопоставлять каждое значение вашего Enum со строковым описанием, и передать его параметром в конвертер:

<FrameworkElement.Resources>
    <col:Hashtable x:Key="Dict" xmlns:s="clr-namespace:System;assembly=mscorlib"
                   xmlns:col="clr-namespace:System.Collections;assembly=mscorlib">
        <s:String x:Key="First">Первый этап</s:String>
        <s:String x:Key="Second">Второй этап</s:String>
        <s:String x:Key="Third">Третий этап</s:String>
        <s:String x:Key="Fourth">Четвертый этап</s:String>
    </col:Hashtable>
    <c:EnumToDescriptionConverter x:Key="conv" Dict="{StaticResource Dict}"/>
</FrameworkElement.Resources>

Окончательная разметка вашего ComboBoxа:

<ComboBox SelectedItem="{Binding Stage, Converter={StaticResource conv}}"
          ItemsSource="{c:Enum c:Stage, Converter={StaticResource conv}}"/>
READ ALSO
Многопоточность C#. Вывод в TextBox

Многопоточность C#. Вывод в TextBox

Имеется файл, где большое количество строкВывод файла осущствляется построчно циклом

579
Как умножить матрицу на вектор(алгоритм)?

Как умножить матрицу на вектор(алгоритм)?

Нужно написать перегруженные функции, которые будут умножать матрицу на матрицу, вектор на матрицу, матрицу на вектор, число на вектор и тдЕдинственный...

299
Цвет пикселя по заданным координатам

Цвет пикселя по заданным координатам

Как можно получить цвет пикселя по координатам x и y ?

202
Биндинг TextBox к одному string в WindowsForms

Биндинг TextBox к одному string в WindowsForms

Мне нужно привязать TextBox к одному stringНужно чтобы при изменении TextBox строка менялась и наоборот

226