Originally posted by: Mitkins, at: Oct 12 '17 at 0:22, at stackoverflow. I edited it to correct minor typos in the original. And to make one of two alterations.
I am trying to find a simple example where the enums are shown as is. All examples I have seen tries to add nice looking display strings but I don't want that complexity. Note: EffectStyle is just an enum.
public enum EffectStyle { Undefined = 0, Yes = 1, No = 2 }
Basically I have a class that holds all the properties that I bind, by first setting the DataContext to this class, and then specifying the binding like this in the xaml file:
<ComboBox ItemsSource="{Binding Path=EffectStyle}"/>
But this doesn't show the enum values in the ComboBox as items.
Using ReactiveUI
, I've created the following alternate solution. It's not an elegant all-in-one solution, but I think at the very least it's readable.
In my case, binding a list of enum
to a control is a rare case, so I don't need to scale the solution across the code base. However, the code can be made more generic by changing EffectStyleLookup.Item
into an Object
. I tested it with my code, no other modifications are necessary. Which means the one helper class could be applied to any enum
list. Though that would reduce its readability - ReactiveList<EnumLookupHelper>
doesn't have a great ring to it.
Using the following helper class:
public class EffectStyleLookup
{
public EffectStyle Item { get; set; }
public string Display { get { return Item.ToString();} }
public EffectStyleLookup(){ }
public EffectStyleLookup(EffectStyle item)
{
this.Item = item;
}
}
Yes. I prefer using constructors. All things considered, you write less code.
In the ViewModel, convert the list of enums and expose it as a property:
public MyViewModel : 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 MyViewModel()
{
this.LoadEffectStyleCombo();
}
private void LoadEffectStyleCombo()
{
// Convert a list of enums into a ReactiveList
var xs = ((IList<EffectStyle>)Enum.GetValues(typeof(EffectStyle)))
.Select( x => new EffectStyleLookup(x) );
EffectStyles = new ReactiveList<EffectStyleLookup>();
EffectStyles.AddRange(xs);
}
}
In the ComboBox
, utilise the SelectedValuePath
property, to bind to the original enum
value:
<ComboBox x:Name="cboEffectStyle" DisplayMemberPath="Display" SelectedValuePath="Item" />
In the View, this allows us to bind the original enum
to the SelectedEffectStyle
in the ViewModel, but display the ToString()
value in the ComboBox
:
public MyView()
{
InitializeComponent();
this.WhenActivated(disposables => this.BindControls(disposables));
}
private void BindControls(CompositeDisposable disposableRegistration)
{
this.OneWayBind(ViewModel, vm => vm.EffectStyles, v => v.cboEffectStyle.ItemsSource).DisposeWith(disposableRegistration);
this.Bind(ViewModel, vm => vm.SelectedEffectStyle, v => v.cboEffectStyle.SelectedValue).DisposeWith(disposableRegistration);
}