On my journey to learning MVVM I've established some basic understanding of WPF and the ViewModel pattern. I'm using the following abstraction when providing a list and am interested in a single selected item.
public ObservableCollection<OrderViewModel> Orders { get; private set; }
public ICollectionView OrdersView
{
get
{
if( _ordersView == null )
_ordersView = CollectionViewSource.GetDefaultView( Orders );
return _ordersView;
}
}
private ICollectionView _ordersView;
public OrderViewModel CurrentOrder
{
get { return OrdersView.CurrentItem as OrderViewModel; }
set { OrdersView.MoveCurrentTo( value ); }
}
I can then bind the OrdersView along with supporting sorting and filtering to a list in WPF:
<ListView ItemsSource="{Binding Path=OrdersView}"
IsSynchronizedWithCurrentItem="True">
This works really well for single selection views. But I'd like to also support multiple selections in the view and have the model bind to the list of selected items.
How would I bind the ListView.SelectedItems to a backer property on the ViewModel?
Add an
IsSelected
property to your child ViewModel (OrderViewModel
in your case):Bind the selected property on the container to this (for ListBox in this case):
IsSelected
is updated to match the corresponding field on the container.You can get the selected children in the view model by doing the following:
I can assure you:
SelectedItems
is indeed bindable as a XAMLCommandParameter
There is a simple solution to this common issue; to make it work you must follow ALL the following rules:
Following Ed Ball's suggestion, on your XAML command databinding, define the
CommandParameter
attribute BEFORE theCommand
attribute. This a very time-consuming bug.Make sure your
ICommand
'sCanExecute
andExecute
methods have a parameter of typeobject
. This way you can prevent silenced cast exceptions that occur whenever the databinding'sCommandParameter
type does not match yourCommand
method's parameter type:For example, you can either send a
ListView
/ListBox
'sSelectedItems
property to yourICommand
methods or theListView
/ListBox
itself. Great, isn't it?I hope this prevents someone from spending the huge amount of time I did to figure out how to receive
SelectedItems
as aCanExecute
parameter.One can try creating an attached property.
Doing so will save one from adding the
IsSelected
property for each and every list you bind. I have done it forListBox
, but it can be modified for use a in a list view.More info: WPF – Binding ListBox SelectedItems – Attached Property VS Style .
If you're using MVVM-LIGHT you can use this pattern:
http://blog.galasoft.ch/archive/2010/05/19/handling-datagrid.selecteditems-in-an-mvvm-friendly-manner.aspx
Not especially elegant but looks like it should be reliable at least