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:
Following Ed Ball's suggestion', on you XAML command databinding, define CommandParameter property BEFORE Command property. This a very time-consuming bug.
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_PropertyChanged
Next
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
.