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; set; }
}
In the ViewModel, convert the list of enums and expose it as a property:
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 );
}
}
In the ComboBox
, utilise the SelectedValuePath
property, to bind to the original enum
value:
<ComboBox Name="EffectStyle" 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
:
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) );
});