3

Still very new to WPF & MVVM so I apologize for this noob question but need some help.

I populate a ListView using ItemSource="{Binding AvailableRoles}". It populates just fine. Now I have the SelectIndex="{Binding SelectedRoles}" to select the correct role after a search. It works fine with one int but it doesn't work for a List or ObservableCollection. SelectionMode="Multiple" is set as well.

private ObservableCollection<int> selectedRoles;
public ObservableCollection<int> SelectedRoles
{
    get { return selectedRoles; }
    set
    {
        selectedRoles = value;
        OnPropertyChanged("SelectedRoles");
    }
}

Is it possible to select multiple rows on ListView by data binding to a List? or how do I go about doing it. I'm trying to not do this on an event in order to follow the MVVM pattern.

FaizanHussainRabbani
  • 3,256
  • 3
  • 26
  • 46
Deadfish
  • 41
  • 7

2 Answers2

3

SelectedIndex only really works when allowing only a single selection.

If we look at the documentation for WPF's ListView, we can see there are couple more properties to leverage:

  • SelectedItem
  • SelectedItems

You want to use SelectedItems. This will give you back a collection of instances from your bound items of what are selected.

As pointed out by Mike in the comments, it is not bindable (I completely forgot about that). You can, however, bind that property specifically to other things to help get around that. For instance you can bind it to a CommandParameter if you only need to do something once the user triggers a Command.

He has built a nice utility to help this issue that you may be able to leverage: Virtualization and SelectionChanged event

TyCobb
  • 8,909
  • 1
  • 33
  • 53
  • Thank you for the response. What should I be passing in on SelectedItems? In SelectIndex I pass in a int as the index. – Deadfish Feb 20 '18 at 18:53
  • You can use the code sample I supplied. Instead of `int` you use instances of your actual items. – TyCobb Feb 20 '18 at 18:57
  • Oh I see, thank you for the help. I will give this a shot. – Deadfish Feb 20 '18 at 19:10
  • `SelectedItems` is a _read-only_ property; you can't bind it (not even with `OneWayToSource` mode). Handling multi-selection in MVVM is rather cumbersome. I submitted an [answer to another question](https://stackoverflow.com/a/48547976/175070) that proposes letting each item track its own selection state, and I included a utility class to maintain a list of selected items based on that state. – Mike Strobel Feb 20 '18 at 20:09
  • @MikeStrobel D'OH! That's right. I forgot all about that crap. You can't bind it, but you can use it as a parameter. I'll update my answer, but I am kind of tempted to just delete it. – TyCobb Feb 20 '18 at 20:58
  • I actually ended up going with a DataGrid. You can bind a List to DataGrid and set which rows you want to see. I still created a Role class like you suggested and put properties: string Description & bool IsChecked. The bool causes the DataGrid to create checkboxes. With checkboxes you can select multiple rows this way. Thank you anyway! – Deadfish Feb 21 '18 at 02:58
0

Ended up using DataGrid. You can select multiple rows by binding a bool property. The boolean will cause DataGrid to create checkboxes either checked or unchecked.

Here's the XAML code used:

    <DataGrid HeadersVisibility="None"
              SelectionMode="Extended"
              AutoGenerateColumns="False"
              CanUserAddRows="False"
              ItemsSource="{Binding ContactRoles, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
        <DataGrid.Columns>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <CheckBox IsChecked="{Binding IsChecked}" Width="Auto"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

            <DataGridTextColumn Header="" Binding="{Binding RoleDescription}" Width="2*" />
        </DataGrid.Columns>
    </DataGrid>
Deadfish
  • 41
  • 7