Search code examples
c#wpflistviewmvvmdata-binding

ListView select multiple items programmatically in MVVM


How can I select several rows into a ListView from the code with MVVM Pattern ?

The ListView that I use was made by a teammate who is no more there

public static readonly DependencyProperty SelectedItemsListProperty = DependencyProperty.Register("SelectedItemsList" , typeof(IList) , typeof(SrListView) , new PropertyMetadata(null));

(...)
public IList SelectedItemsList
        {
            get
            {
                return ( IList )GetValue(SelectedItemsListProperty);
            }
            set
            {
                SetValue(SelectedItemsListProperty , value);
            }
        }

(...)

private void SrListView_SelectionChanged(object sender , SelectionChangedEventArgs e)
        {
            SelectedItemsList = SelectedItems;
        }

I use this listview like this :

<CustomListView SelectionMode="Extended"
                ItemsSource="{Binding ocPackages}"
                SelectedItem="{Binding objSelectedPackage}"
                SelectedItemsList="{Binding ilSelectedPackages, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</CustomListView>
        private IList _ilSelectedPackages; // = new ArrayList()
        public IList ilSelectedPackages
        {
            get
            {
                return _ilSelectedPackages;
            }
            set
            {
                _ilSelectedPackages = value;
                OnPropertyChanged(nameof(ilSelectedPackages));
            }
        }
ilSelectedPackages.Clear();
ilSelectedPackages.Add(objDTO_PackageToSelect);

I try to clear and then fill ilSelectedPackages but this has no effect on the selection of the ListView :(

I found this topic Managing multiple selections with MVVM but I'm not able to solve my problem with it :(

Edit 1 : The "Multiselect ListBox" topic doesn't help me to solve my problem because it is not implemented in the ListViews by default, in my question I explain that it's a homemade ListView and how "SelectedItemsList" was added to the default ListView.

Edit 2 : I tried to modify the homemade ListView component by a "BindableTwoWay" behaviour without success after watching this answer https://stackoverflow.com/a/51254960/10617386 :

public static readonly DependencyProperty SelectedItemsListProperty = DependencyProperty.Register("SelectedItemsList", typeof(IList), typeof(SrListView), new FrameworkPropertyMetadata(default(IList),
                                                  FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedItemsListChanged));

(...)

private static void OnSelectedItemsListChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
     if (d is SrListView ListView)
          ListView.SetSelectedItems(ListView.SelectedItemsList);
}

Thanks per advance for your help


Solution

  • I finally found the solution, the problem was not in the homemade component as I was first thinking (I was not searching in the right area) but simply when I was selecting the objects with :

    ilSelectedPackages.Add(objDTO_PackageToSelect);
    

    objDTO_PackageToSelect was a copy of an object and so was not comming from ocPackages the ObservableCollection that was filling the ListView.

    Conclusion : We must select the exact objects of the Binded observable collection.

    DTO_Package objPackInOC = ocPackages.Where(Pack => Pack.sGuid == objDTO_PackageToSelect.sGuid).FirstOrDefault();
    
    if(objPackInOC != null)
         ilSelectedPackages.Add(objPackInOC);