views:

1905

answers:

4

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?

+6  A: 

Here's what I've seen Josh Smith do.

Add an IsSelected property to your child ViewModel (OrderViewModel in your case):

public bool IsSelected { get; set; }

Bind the selected property on the container to this (for ListBox in this case):

<ListBox.ItemContainerStyle>
    <Style TargetType="{x:Type ListBoxItem}">
        <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
    </Style>
</ListBox.ItemContainerStyle>

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:

public IEnumerable<OrderViewModel> SelectedOrders
{
    get { return Orders.Where(o => o.IsSelected); }
}
Josh G
Please note that this solution is not working when using a VirtualizingStackPanel in the ListBox (which is the default). More info at this post : http://stackoverflow.com/questions/1273659/virtualizingstackpanel-mvvm-multiple-selection
decasteljau
Good catch. Thanks for the update. For single selection, the best solution is ICollectionView. Microsoft needs to create an ICollectionView interface that supports multi-selection.
Josh G
You have just saved my life!
jpsstavares
A: 

I have created a MultiSelectCollectionView that you might find useful here:

http://grokys.blogspot.com/2010/07/mvvm-and-multiple-selection-part-iii.html

Groky
note: this uses some classes not present in Silverlight 4. if you need this for Silverlight you'd need to change a few things. MultiSelector and ListCollectionView don't exist for instance. if anyone has adapted this for silverlight would love to see it
Simon_Weaver
A: 

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

Simon_Weaver
hmm it actually only goes one way with this method (view > view model). not capable of view model > view as described here
Simon_Weaver
A: 

Here's another solution which I just used to solve this problem and I found it rather elegant: http://alexshed.spaces.live.com/blog/cns!71C72270309CE838!149.entry

RyanHennig