You can bind directly the SelectedItem
listobx property to your view model but not the SelectedItems
property.
I used a behavior to achieve this associated with a delegate command (included in the Prism framework)
Your object
class MyObject
{
}
The behavior
internal class MyObjectSelectionChangedToCommand
{
public static readonly DependencyProperty SelectionCommandProperty =
DependencyProperty.RegisterAttached("SelectionCommand", typeof(DelegateCommand<GridSelectionInfo<MyObject>>),
typeof(ResourceCardGridSelectionChangedToCommand), new PropertyMetadata(null, OnSelectionCommandChanged));
public static DelegateCommand<GridSelectionInfo<MyObject>> GetSelectionCommand(DependencyObject obj)
{
return (DelegateCommand<GridSelectionInfo<MyObject>>)obj.GetValue(SelectionCommandProperty);
}
public static void SetSelectionCommand(DependencyObject obj, DelegateCommand<GridSelectionInfo<MyObject>> value)
{
obj.SetValue(SelectionCommandProperty, value);
}
private static void dg_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var tsci = new GridSelectionInfo<MyObject>
{
Added = e.AddedItems.Cast<MyObject>().ToList(),
Removed = e.RemovedItems.Cast<MyObject>().ToList(),
Selected = ((ListBox)sender).SelectedItems.Cast<MyObject>().ToList()
};
var cmd = GetSelectionCommand((DependencyObject)sender);
cmd.Execute(tsci);
}
private static void OnSelectionCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var dg = d as ListBox;
if (dg != null) dg.SelectionChanged += dg_SelectionChanged;
}
}
public class GridSelectionInfo<T>
{
public GridSelectionInfo()
{
Selected = new List<T>();
Added = new List<T>();
Removed = new List<T>();
}
public List<T> Added { get; set; }
public List<T> Removed { get; set; }
public List<T> Selected { get; set; }
public override string ToString()
{
return string.Format("Added: {0}, Removed: {1}, Selected: {2}", Added.Count, Removed.Count, Selected.ToFormattedString());
}
}
The XAML part where you bind the view model command to the behavior
<ListBox ItemsSource="{Binding MyCollection}"
resources:ResourceCardGridSelectionChangedToCommand.SelectionCommand="{Binding CmdObjectSelectionChanged}">
</ListBox>
Then, in you view model you just have to declare the command
public DelegateCommand<GridSelectionInfo<MyObject>> CmdObjectSelectionChanged { get; private set; }
And create it
CmdObjectSelectionChanged = new DelegateCommand<<GridSelectionInfo<MyObject>>(ExecuteSelect,CanExecuteSelect);
Thus, every time the selection changes in your listbox, you will receive all the info about selected items in the execute delegate wrapped in the GridSelectionInfo
object;