Reputation: 4950
I have an Enum defined, my intention is to display the four options(None, Left, Center, and Right) to a user in a ListBox. This ListBox will allow for multiple selections. When the save command is clicked I must pass the selections to the ViewModel where I will aggregate the selections and pass this to a WCF service.
Enum:
[DataContract]
[Flags]
public enum Locations
{
None = 0,
[EnumMember]
Left = 1,
[EnumMember]
Center = 2,
[EnumMember]
Right = 4,
[EnumMember]
LeftCenter = Left | Center,
[EnumMember]
LeftRight = Left | Right,
[EnumMember]
CenterRight = Center | Right,
[EnumMember]
All = Left | Center | Right
}
XAML:
<Button Command="{Binding SaveCommand}"
CommandParameter="{Binding SelectedItems, ElementName=lbLocations}" />
<ListBox x:Name="lbLocations" SelectionMode="Multiple">
<ListBoxItem Content="{x:Static m:Subsections.None}" />
<ListBoxItem Content="{x:Static m:Subsections.Left}" />
<ListBoxItem Content="{x:Static m:Subsections.Center}" />
<ListBoxItem Content="{x:Static m:Subsections.Right}" />
</ListBox>
ViewModel:
public ICommand SaveCommand
{
get
{
if (_saveCommand == null)
_saveCommand = new RelayCommand<IList>(x => Save(x));
return _saveCommand;
}
}
private void Save(IList locations)
{
try
{
// ToList() produces InvalidCastException.
var collection = locations.Cast<Locations>().ToList();
// Do WCF stuff, display success, etc.
}
catch (Exception ex)
{
_dialogService.Show(ex.Message, "Error");
}
}
I have successfully passed the selections back to my ViewModel as an IList, but I'm having difficulty casting it back to my enum. Is there a better approach I have overlooked, can this work? It seems like I'm nearly there.
Upvotes: 2
Views: 140
Reputation: 10744
There is a better way to achieve this:
Create a class to hold data for each item in the ListBox
class EnumSelection
{
public bool IsSelected { get; set; }
public Subsections Value { get; set; }
public EnumSelection(Subsections value)
{
Value = value;
}
}
Bind the ItemsSource
property of the ListBox
to the available enums
private IEnumerable<EnumSelection> enums;
public IEnumerable<EnumSelection> Enums
{
get
{
if (this.enums == null)
{
this.enums = Enum.GetValues(typeof(Subsections)).Cast<Subsections>().Select(s => new EnumSelection(s));
}
return this.enums;
}
}
public IEnumerable<EnumSelection> SelectedItems
{
get
{
return Enums.Where(e => e.IsSelected);
}
}
Use a DataTemplate to bind to the new class
<ListBox ItemsSource="{Binding Enums}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected}"/>
<TextBlock Text="{Binding Value}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Save method:
ICommand _saveCommand;
public ICommand SaveCommand
{
get
{
return this._saveCommand
?? (this._saveCommand = new RelayCommand<IEnumerable<EnumSelection>>(x => this.Save(x)));
}
}
private void Save(IEnumerable<EnumSelection> enums)
{
}
Upvotes: 0
Reputation: 4978
Try iterating through the casted list and aggregating the value into a single variable, like this:
private void Save(IList locations)
{
try
{
Locations location = Locations.None;
foreach (Locations value in locations.Cast<Locations>())
{
location |= value;
}
// Do WCF stuff, display success, etc.
}
catch (Exception ex)
{
_dialogService.Show(ex.Message, "Error");
}
}
Upvotes: 1