Jak powiązać enum z kontrolką combobox w WPF?

Próbuję znaleźć prosty przykład, gdzie liczby są pokazane tak, jak jest. Wszystkie przykłady widziałem próbuje dodać ładnie wyglądające ciągi wyświetlania, ale nie chcę, że złożoność.

Zasadniczo mam klasę, która przechowuje wszystkie właściwości, które wiążę, najpierw ustawiając DataContext na tę klasę, A następnie określając Wiązanie w ten sposób w pliku xaml:

<ComboBox ItemsSource="{Binding Path=EffectStyle}"/>

Ale to nie pokazuje wartości enum w ComboBox jako pozycji.

Author: Andy, 2011-05-27

15 answers

Możesz to zrobić z kodu, umieszczając następujący kod w oknie Loaded obsługa zdarzeń, na przykład:

yourComboBox.ItemsSource = Enum.GetValues(typeof(EffectStyle)).Cast<EffectStyle>();

Jeśli chcesz go powiązać w XAML, musisz użyć ObjectDataProvider, Aby utworzyć obiekt dostępny jako źródło powiązania:

<Window x:Class="YourNamespace.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:System="clr-namespace:System;assembly=mscorlib"
        xmlns:StyleAlias="clr-namespace:Motion.VideoEffects">
    <Window.Resources>
        <ObjectDataProvider x:Key="dataFromEnum" MethodName="GetValues"
                            ObjectType="{x:Type System:Enum}">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="StyleAlias:EffectStyle"/>
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>
    <Grid>
        <ComboBox ItemsSource="{Binding Source={StaticResource dataFromEnum}}"
                  SelectedItem="{Binding Path=CurrentEffectStyle}" />
    </Grid>
</Window>

Zwróć uwagę na następny kod:

xmlns:System="clr-namespace:System;assembly=mscorlib"
xmlns:StyleAlias="clr-namespace:Motion.VideoEffects"

Przewodnik jak mapować przestrzeń nazw i assembly możesz przeczytać na MSDN.

 245
Author: Kyrylo M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-21 18:13:35

Lubię, gdy wszystkie obiekty, które wiążę, mają być zdefiniowane w moim ViewModel, więc staram się unikać używania <ObjectDataProvider> w xaml, jeśli to możliwe.

Moje rozwiązanie nie używa żadnych danych zdefiniowanych w widoku i żadnego kodu-behind. Tylko DataBinding, ValueConverter wielokrotnego użytku, metoda uzyskiwania zbioru opisów dla dowolnego typu Enum oraz pojedyncza właściwość w ViewModel do powiązania.

Gdy chcę powiązać Enum z ComboBox tekst, który chcę wyświetlić, nigdy nie pasuje do wartości Enum, więc użyj atrybutu [Description()], aby nadać mu tekst, który chcę zobaczyć w ComboBox. Jeśli miałbym wyliczenie klas postaci w grze, wyglądałoby to mniej więcej tak:]}

public enum PlayerClass
{
  // add an optional blank value for default/no selection
  [Description("")]
  NOT_SET = 0,
  [Description("Shadow Knight")]
  SHADOW_KNIGHT,
  ...
}

Najpierw stworzyłem klasę pomocniczą z kilkoma metodami do radzenia sobie z enumami. Jedna metoda pobiera opis dla określonej wartości, druga metoda pobiera wszystkie wartości i ich opisy dla danego typu.

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();
  }
}

Następnie tworzymy ValueConverter. Dziedziczenie z MarkupExtension ułatwia korzystanie z XAML, więc nie mamy zadeklarować go jako zasób.

[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;
  }
}

Mój ViewModel potrzebuje tylko 1 Właściwości, z którą mój View może się wiązać zarówno dla SelectedValue jak iItemsSource comboboxu:

private PlayerClass playerClass;

public PlayerClass SelectedClass
{
  get { return playerClass; }
  set
  {
    if (playerClass != value)
    {
      playerClass = value;
      OnPropertyChanged(nameof(SelectedClass));
    }
  }
}

I na koniec do wiązania widoku ComboBox (używając ValueConverter w wiązaniu ItemsSource)...

<ComboBox ItemsSource="{Binding Path=SelectedClass, Converter={x:EnumToCollectionConverter}, Mode=OneTime}"
          SelectedValuePath="Value"
          DisplayMemberPath="Description"
          SelectedValue="{Binding Path=SelectedClass}" />

Aby zaimplementować to rozwiązanie wystarczy skopiować moją EnumHelper klasę i EnumToCollectionConverter klasę. Będą pracować z dowolnymi enumami. Poza tym, nie zamieściłem tego tutaj, ale ValueDescription klasa jest po prostu prostą klasą z 2 obiektami publicznymi właściwości, jeden o nazwie Value, jeden o nazwie Description. Możesz go utworzyć samodzielnie lub zmienić kod na Tuple<object, object> lub KeyValuePair<object, object>

 93
Author: Nick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-27 22:09:12

Użyłem innego rozwiązania przy użyciu MarkupExtension.

  1. Zrobiłem klasę, która dostarcza elementów źródło:

    public class EnumToItemsSource : MarkupExtension
    {
        private readonly Type _type;
    
        public EnumToItemsSource(Type type)
        {
            _type = type;
        }
    
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return Enum.GetValues(_type)
                .Cast<object>()
                .Select(e => new { Value = (int)e, DisplayName = e.ToString() });
        }
    }
    
  2. To prawie wszystko... Teraz użyj go w XAML:
        <ComboBox DisplayMemberPath="DisplayName"
              ItemsSource="{persons:EnumToItemsSource {x:Type enums:States}}"
              SelectedValue="{Binding Path=WhereEverYouWant}"
              SelectedValuePath="Value" />
    
  3. Zmień "enums: States" na swoje enum

 41
Author: tom.maruska,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-17 19:56:44

Użyj ObjectDataProvider:

<ObjectDataProvider x:Key="enumValues"
   MethodName="GetValues" ObjectType="{x:Type System:Enum}">
      <ObjectDataProvider.MethodParameters>
           <x:Type TypeName="local:ExampleEnum"/>
      </ObjectDataProvider.MethodParameters>
 </ObjectDataProvider>

A następnie bind do zasobu statycznego:

ItemsSource="{Binding Source={StaticResource enumValues}}"
 17
Author: druss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-27 16:55:11

Odpowiedź Nicka naprawdę mi pomogła, ale zdałem sobie sprawę, że można ją lekko podkręcić, żeby uniknąć dodatkowej klasy, wartościowej. Przypomniaĺ ' em sobie, Ĺźe istnieje klasa KeyValuePair juĹź w frameworku, wiÄ ™ c moĹźe ona byÄ ‡ uĺźywana zamiast niej.

Kod zmienia się tylko nieznacznie:

public static IEnumerable<KeyValuePair<string, string>> GetAllValuesAndDescriptions<TEnum>() where TEnum : struct, IConvertible, IComparable, IFormattable
    {
        if (!typeof(TEnum).IsEnum)
        {
            throw new ArgumentException("TEnum must be an Enumeration type");
        }

        return from e in Enum.GetValues(typeof(TEnum)).Cast<Enum>()
               select new KeyValuePair<string, string>(e.ToString(),  e.Description());
    }


public IEnumerable<KeyValuePair<string, string>> PlayerClassList
{
   get
   {
       return EnumHelper.GetAllValuesAndDescriptions<PlayerClass>();
   }
}

I na koniec XAML :

<ComboBox ItemSource="{Binding Path=PlayerClassList}"
          DisplayMemberPath="Value"
          SelectedValuePath="Key"
          SelectedValue="{Binding Path=SelectedClass}" />
Mam nadzieję, że to pomoże innym.
 9
Author: Roger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-30 13:58:21

Musisz utworzyć tablicę wartości w enum, którą można utworzyć przez wywołanie System.Enum.GetValues () , przekazując jej Type z enum, którego chcesz mieć elementy.

Jeśli określisz to dla właściwości ItemsSource, to powinna ona być wypełniona wszystkimi wartościami enum. Prawdopodobnie chcesz powiązać SelectedItem z EffectStyle (zakładając, że jest to właściwość tego samego enum i zawiera bieżącą wartość).

 8
Author: Andy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-26 22:37:10

Wszystkie powyższe posty ominęły prostą sztuczkę. Jest to możliwe dzięki powiązaniu SelectedValue, aby dowiedzieć się, jak automatycznie wypełnić ItemsSource tak, aby znaczniki XAML były sprawiedliwe.

<Controls:EnumComboBox SelectedValue="{Binding Fool}"/>

Na przykład w moim ViewModel mam

public enum FoolEnum
    {
        AAA, BBB, CCC, DDD

    };


    FoolEnum _Fool;
    public FoolEnum Fool
    {
        get { return _Fool; }
        set { ValidateRaiseAndSetIfChanged(ref _Fool, value); }
    }

ValidateRaiseAndSetIfChanged to mój hook INPC. Twoje mogą się różnić.

Implementacja EnumComboBox jest następująca, ale najpierw potrzebuję małego helpera, aby uzyskać moje ciągi i wartości enumeracji

    public static List<Tuple<object, string, int>> EnumToList(Type t)
    {
        return Enum
            .GetValues(t)
            .Cast<object>()
            .Select(x=>Tuple.Create(x, x.ToString(), (int)x))
            .ToList();
    }

I główna klasa (Uwaga używam ReactiveUI do zaczepiania zmian właściwości poprzez WhenAny)

using ReactiveUI;
using ReactiveUI.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Documents;

namespace My.Controls
{
    public class EnumComboBox : System.Windows.Controls.ComboBox
    {
        static EnumComboBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(EnumComboBox), new FrameworkPropertyMetadata(typeof(EnumComboBox)));
        }

        protected override void OnInitialized( EventArgs e )
        {
            base.OnInitialized(e);

            this.WhenAnyValue(p => p.SelectedValue)
                .Where(p => p != null)
                .Select(o => o.GetType())
                .Where(t => t.IsEnum)
                .DistinctUntilChanged()
                .ObserveOn(RxApp.MainThreadScheduler)
                .Subscribe(FillItems);
        }

        private void FillItems(Type enumType)
        {
            List<KeyValuePair<object, string>> values = new List<KeyValuePair<object,string>>();

            foreach (var idx in EnumUtils.EnumToList(enumType))
            {
                values.Add(new KeyValuePair<object, string>(idx.Item1, idx.Item2));
            }

            this.ItemsSource = values.Select(o=>o.Key.ToString()).ToList();

            UpdateLayout();
            this.ItemsSource = values;
            this.DisplayMemberPath = "Value";
            this.SelectedValuePath = "Key";

        }
    }
}

Musisz również poprawnie ustawić styl w Generic.XAML lub Twoja skrzynka nic nie renderuje, a Ty wyrywasz włosy.

<Style TargetType="{x:Type local:EnumComboBox}" BasedOn="{StaticResource {x:Type ComboBox}}">
</Style>

I tyle. Oczywiście można by to rozszerzyć na obsługę i18n, ale wydłużyłoby post.

 4
Author: bradgonesurfing,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-17 12:51:16
public class EnumItemsConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!value.GetType().IsEnum)
            return false;

        var enumName = value.GetType();
        var obj = Enum.Parse(enumName, value.ToString());

        return System.Convert.ToInt32(obj);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Enum.ToObject(targetType, System.Convert.ToInt32(value));
    }
}

Powinieneś rozszerzyć odpowiedź Rogersa i Grega o taki konwerter wartości Enum, jeśli wiążesz bezpośrednio z właściwościami modelu obiektowego enum.

 2
Author: Ruberoid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-08 16:30:06

Uniwersalne aplikacje wydają się działać nieco inaczej; nie ma całej mocy w pełni funkcjonalnego XAML. U mnie działa:

  1. utworzyłem listę wartości enum jako enum (nie konwertowane do strings lub do liczb całkowitych) i powiązał ComboBox ItemsSource z tym
  2. wtedy mógłbym powiązać Elementy Comboboxu z moją własnością publiczną którego typem jest dany enum

Dla Zabawy dodałem trochę template class, aby w tym pomóc i opublikowałem do stron MSDN Samples . Dodatkowe bity pozwalają mi opcjonalnie nadpisać nazwy enum i pozwolić mi ukryć niektóre z enum. Mój kod wygląda okropnie jak Nick (powyżej), którego żałuję, że nie widziałem wcześniej.

Uruchamianie próbki; zawiera ona wiele wiązań dwuwarstwowych do enum

 2
Author: rsclient,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-26 16:48:42

Jeśli wiążesz się z rzeczywistą właściwością enum w modelu widoku, a nie z reprezentacją int enum, sprawy stają się trudne. Stwierdziłem, że konieczne jest powiązanie z reprezentacją ciągu znaków, a nie wartością int, jak jest to oczekiwane we wszystkich powyższych przykładach.

Możesz określić, czy tak jest, wiążąc proste pole tekstowe z właściwością, którą chcesz powiązać w modelu widoku. Jeśli wyświetla tekst, połącz z ciągiem znaków. Jeśli pokazuje liczbę, połącz ją z wartością. Uwaga użyłem wyświetlacza dwa razy, który normalnie byłby to błąd, ale tylko tak to działa.

<ComboBox SelectedValue="{Binding ElementMap.EdiDataType, Mode=TwoWay}"
                      DisplayMemberPath="Display"
                      SelectedValuePath="Display"
                      ItemsSource="{Binding Source={core:EnumToItemsSource {x:Type edi:EdiDataType}}}" />

Greg

 1
Author: Greg0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-17 20:06:55

Podobał mi się tom.odpowiedź maruska , ale musiałem obsługiwać każdy typ enum, który mój szablon może napotkać w czasie wykonywania. W tym celu musiałem użyć wiązania, aby określić typ rozszerzenia znaczników. Byłem w stanie pracować w ta odpowiedź od nicolay.anykienko wymyślić bardzo elastyczne rozszerzenie znaczników, które będzie działać w każdym przypadku mogę myśleć. Jest spożywany w ten sposób:

<ComboBox SelectedValue="{Binding MyEnumProperty}" 
          SelectedValuePath="Value"
          ItemsSource="{local:EnumToObjectArray SourceEnum={Binding MyEnumProperty}}" 
          DisplayMemberPath="DisplayName" />

Źródło rozszerzenia mashed up markup, o którym mowa powyżej:

class EnumToObjectArray : MarkupExtension
{
    public BindingBase SourceEnum { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        IProvideValueTarget target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
        DependencyObject targetObject;
        DependencyProperty targetProperty;

        if (target != null && target.TargetObject is DependencyObject && target.TargetProperty is DependencyProperty)
        {
            targetObject = (DependencyObject)target.TargetObject;
            targetProperty = (DependencyProperty)target.TargetProperty;
        }
        else
        {
            return this;
        }

        BindingOperations.SetBinding(targetObject, EnumToObjectArray.SourceEnumBindingSinkProperty, SourceEnum);

        var type = targetObject.GetValue(SourceEnumBindingSinkProperty).GetType();

        if (type.BaseType != typeof(System.Enum)) return this;

        return Enum.GetValues(type)
            .Cast<Enum>()
            .Select(e => new { Value=e, Name = e.ToString(), DisplayName = Description(e) });
    }

    private static DependencyProperty SourceEnumBindingSinkProperty = DependencyProperty.RegisterAttached("SourceEnumBindingSink", typeof(Enum)
                       , typeof(EnumToObjectArray), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));

    /// <summary>
    /// Extension method which returns the string specified in the Description attribute, if any.  Oherwise, name is returned.
    /// </summary>
    /// <param name="value">The enum value.</param>
    /// <returns></returns>
    public static string Description(Enum value)
    {
        var attrs = value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
        if (attrs.Any())
            return (attrs.First() as DescriptionAttribute).Description;

        //Fallback
        return value.ToString().Replace("_", " ");
    }
}
 1
Author: Hamish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:20

Jest wiele doskonałych odpowiedzi na to pytanie i pokornie przedstawiam swoje. Uważam, że mój jest nieco prostszy i bardziej elegancki. Wymaga tylko konwertera wartości.

Podano enum...

public enum ImageFormat
{
    [Description("Windows Bitmap")]
    BMP,
    [Description("Graphics Interchange Format")]
    GIF,
    [Description("Joint Photographic Experts Group Format")]
    JPG,
    [Description("Portable Network Graphics Format")]
    PNG,
    [Description("Tagged Image Format")]
    TIFF,
    [Description("Windows Media Photo Format")]
    WDP
}

I przelicznik wartości...

public class ImageFormatValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is ImageFormat format)
        {
            return GetString(format);
        }

        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is string s)
        {
            return Enum.Parse(typeof(ImageFormat), s.Substring(0, s.IndexOf(':')));
        }
        return null;
    }

    public string[] Strings => GetStrings();

    public static string GetString(ImageFormat format)
    {
        return format.ToString() + ": " + GetDescription(format);
    }

    public static string GetDescription(ImageFormat format)
    {
        return format.GetType().GetMember(format.ToString())[0].GetCustomAttribute<DescriptionAttribute>().Description;

    }
    public static string[] GetStrings()
    {
        List<string> list = new List<string>();
        foreach (ImageFormat format in Enum.GetValues(typeof(ImageFormat)))
        {
            list.Add(GetString(format));
        }

        return list.ToArray();
    }
}

Zasoby...

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

Deklaracja XAML...

    <ComboBox Grid.Row="9" ItemsSource="{Binding Source={StaticResource ImageFormatValueConverter}, Path=Strings}"
              SelectedItem="{Binding Format, Converter={StaticResource ImageFormatValueConverter}}"/>

Model widoku...

    private ImageFormat _imageFormat = ImageFormat.JPG;
    public ImageFormat Format
    {
        get => _imageFormat;
        set
        {
            if (_imageFormat != value)
            {
                _imageFormat = value;
                OnPropertyChanged();
            }
        }
    }

Powstały combobox...

ComboBox związany z enum

 1
Author: AQuirky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-28 19:29:15

Używając ReactiveUI, stworzyłem następujące alternatywne rozwiązanie. Nie jest to eleganckie rozwiązanie all-in-one, ale myślę, że przynajmniej jest czytelne.

W moim przypadku Wiązanie listy enum do kontrolki jest rzadkim przypadkiem, więc nie muszę skalować rozwiązania w całej bazie kodu. Jednak kod może być bardziej ogólny, zmieniając EffectStyleLookup.Item na Object. Przetestowałem go za pomocą mojego kodu, żadne inne modyfikacje nie są konieczne. Co oznacza, że jedna klasa pomocnicza może być zastosowana do dowolnego enum lista. Chociaż zmniejszyłoby to jego czytelność- ReactiveList<EnumLookupHelper> nie ma w tym wielkiego znaczenia.

Używając następującej klasy pomocniczej:

public class EffectStyleLookup
{
    public EffectStyle Item { get; set; }
    public string Display { get; set; }
}

W ViewModel, Konwertuj listę enum i wystawiaj ją jako właściwość:

public ViewModel : ReactiveObject
{
  private ReactiveList<EffectStyleLookup> _effectStyles;
  public ReactiveList<EffectStyleLookup> EffectStyles
  {
    get { return _effectStyles; }
    set { this.RaiseAndSetIfChanged(ref _effectStyles, value); }
  }

  // See below for more on this
  private EffectStyle _selectedEffectStyle;
  public EffectStyle SelectedEffectStyle
  {
    get { return _selectedEffectStyle; }
    set { this.RaiseAndSetIfChanged(ref _selectedEffectStyle, value); }
  }

  public ViewModel() 
  {
    // Convert a list of enums into a ReactiveList
    var list = (IList<EffectStyle>)Enum.GetValues(typeof(EffectStyle))
      .Select( x => new EffectStyleLookup() { 
        Item = x, 
        Display = x.ToString()
      });

    EffectStyles = new ReactiveList<EffectStyle>( list );
  }
}

W ComboBox użyj właściwości SelectedValuePath, aby powiązać z oryginalną enum wartością:

<ComboBox Name="EffectStyle" DisplayMemberPath="Display" SelectedValuePath="Item" />

W widoku, to pozwala nam powiązać Oryginalny enum z SelectedEffectStyle w ViewModel, ale wyświetla ToString() wartość w ComboBox:

this.WhenActivated( d =>
{
  d( this.OneWayBind(ViewModel, vm => vm.EffectStyles, v => v.EffectStyle.ItemsSource) );
  d( this.Bind(ViewModel, vm => vm.SelectedEffectStyle, v => v.EffectStyle.SelectedValue) );
});
 0
Author: Mitkins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-12 00:46:49

Dodaję swój komentarz (w VB, niestety, ale pojęcie można łatwo skopiować do C# w mgnieniu oka), ponieważ po prostu musiałem odwołać się do tego i nie spodobała mi się żadna z odpowiedzi, ponieważ były zbyt skomplikowane. To nie powinno być takie trudne.

Więc wymyśliłem łatwiejszy sposób. Powiązać wyliczenia ze słownikiem. Połącz ten słownik z Comboboxem.

Mój combobox:

<ComboBox x:Name="cmbRole" VerticalAlignment="Stretch" IsEditable="False" Padding="2" 
    Margin="0" FontSize="11" HorizontalAlignment="Stretch" TabIndex="104" 
    SelectedValuePath="Key" DisplayMemberPath="Value" />

Mój kod-tył. Mam nadzieję, że to pomoże komuś innemu.

Dim tDict As New Dictionary(Of Integer, String)
Dim types = [Enum].GetValues(GetType(Helper.Enumerators.AllowedType))
For Each x As Helper.Enumerators.AllowedType In types
    Dim z = x.ToString()
    Dim y = CInt(x)
    tDict.Add(y, z)
Next

cmbRole.ClearValue(ItemsControl.ItemsSourceProperty)
cmbRole.ItemsSource = tDict
 0
Author: Laki Politis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-26 21:50:05

Proste i jasne wyjaśnienie: http://brianlagunas.com/a-better-way-to-data-bind-enums-in-wpf/

xmlns:local="clr-namespace:BindingEnums"
xmlns:sys="clr-namespace:System;assembly=mscorlib"

...

<Window.Resources>
    <ObjectDataProvider x:Key="dataFromEnum" MethodName="GetValues"
                        ObjectType="{x:Type sys:Enum}">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="local:Status"/>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>

...

<Grid>
    <ComboBox HorizontalAlignment="Center" VerticalAlignment="Center" MinWidth="150"
              ItemsSource="{Binding Source={StaticResource dataFromEnum}}"/>
</Grid>
 0
Author: jlo-gmail,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-17 21:18:52