Bind to SelectedItems from DataGrid or ListBox in MVVM Bind to SelectedItems from DataGrid or ListBox in MVVM wpf wpf

Bind to SelectedItems from DataGrid or ListBox in MVVM


SelectedItems is bindable as a XAML CommandParameter.

After a lot of digging and googling, I have finally found a simple solution to this common issue.

To make it work you must follow ALL the following rules:

  1. Following Ed Ball's suggestion', on you XAML command databinding, define CommandParameter property BEFORE Command property. This a very time-consuming bug.

    enter image description here

  2. Make sure your ICommand's CanExecute and Execute methods have a parameter of object type. This way you can prevent silenced cast exceptions that occurs whenever databinding CommandParameter type does not match your command method's parameter type.

    private bool OnDeleteSelectedItemsCanExecute(object SelectedItems)  {    // Your code goes here}private bool OnDeleteSelectedItemsExecute(object SelectedItems)  {    // Your code goes here}

For example, you can either send a listview/listbox's SelectedItems property to you ICommand methods or the listview/listbox it self. Great, isn't it?

Hope it prevents someone spending the huge amount of time I did to figure out how to receive SelectedItems as CanExecute parameter.


You cannot bind to SelectedItems because it is a read-only property. One fairly MVVM-friendly way to work around this is to bind to the IsSelected property of DataGridRow.

You can set up the binding like this:

<DataGrid ItemsSource="{Binding DocumentViewModels}"          SelectionMode="Extended">    <DataGrid.Resources>        <Style TargetType="DataGridRow">            <Setter Property="IsSelected"                    Value="{Binding IsSelected}" />        </Style>    </DataGrid.Resources></DataGrid>

Then you need to create a DocumentViewModel that inherits from ViewModelBase (or whatever MVVM base class you are using) and has the properties of your Document you want to present in the DataGrid, as well as an IsSelected property.

Then, in your main view model, you create a List(Of DocumentViewModel) called DocumentViewModels to bind your DataGrid to. (Note: if you will be adding/removing items from the list, use an ObservableCollection(T) instead.)

Now, here's the tricky part. You need to hook into the PropertyChanged event of each DocumentViewModel in your list, like this:

For Each documentViewModel As DocumentViewModel In DocumentViewModels    documentViewModel.PropertyChanged += DocumentViewModel_PropertyChangedNext

This allows you to respond to changes in any DocumentViewModel.

Finally, in DocumentViewModel_PropertyChanged, you can loop through your list (or use a Linq query) to grab the info for each item where IsSelected = True.


With a bit of trickery you can extend the DataGrid to create a bindable version of the SelectedItems property. My solution requires the binding to have Mode=OneWayToSource since I only want to read from the property anyway, but it might be possible to extend my solution to allow the property to be read-write.

I assume a similar technique could be used for ListBox, but I haven't tried it.

public class BindableMultiSelectDataGrid : DataGrid{    public static readonly DependencyProperty SelectedItemsProperty =        DependencyProperty.Register("SelectedItems", typeof(IList), typeof(BindableMultiSelectDataGrid), new PropertyMetadata(default(IList)));    public new IList SelectedItems    {        get { return (IList)GetValue(SelectedItemsProperty); }        set { throw new Exception("This property is read-only. To bind to it you must use 'Mode=OneWayToSource'."); }    }    protected override void OnSelectionChanged(SelectionChangedEventArgs e)    {        base.OnSelectionChanged(e);        SetValue(SelectedItemsProperty, base.SelectedItems);    }}