简体   繁体   中英

New Xamarin.Forms CollectionView doesn't allow multi pre-selection

I have a CollectionView in my Xamarin.Forms project:

<CollectionView ItemsSource="{Binding Categories}" ItemSizingStrategy="MeasureFirstItem" x:Name="CategoryColView"
                SelectionMode="Multiple" SelectionChangedCommand="{Binding SelectionChangedCommand}" 
                SelectionChangedCommandParameter="{Binding Source={x:Reference CategoryColView}, Path=SelectedItems}"
                SelectedItems="{Binding SelectedCategoryItems}">
   <CollectionView.ItemTemplate>
      <DataTemplate>
         <StackLayout ...>
            <BoxView .../>
               <StackLayout ...>
                  <Label .../>
                     <Image .../>
               </StackLayout>
            <BoxView/>
         </StackLayout>
      </DataTemplate>
   </CollectionView.ItemTemplate>
</CollectionView>

I included the entire XAML element, but the only important part is the SelectedItems property. It is bound to the following viewmodel implementation:

class ViewModel {

    private ObservableCollection<object> selectedCategories { get; set; }
    public ObservableCollection<object> SelectedCategories {
        get => selectedCategories;
        set {
            selectedCategories = value;
            OnPropertyChanged();
        }

    //...

    ctor() {
        //...
        var alreadySelectedCategoryItems = alreadySelectedCategories.Select(pc => new CategoryItem { PlantCategory = pc, IsSelected = true }).Cast<object>();
        SelectedCategoryItems = new ObservableCollection<object>(alreadySelectedCategoryItems);
        //...
    }
}

The rest of the implementation should be irrelevant. My aim is to have pre-selected values.

First: I noticed that if the T in ObservableCollection<T> is not object , everything is ignored. Just like in Microsoft's example here . If the T is eg of type CategoryItem , literally nothing happens, as if the ObserveableCollection were completely ignored.

Second: alreadySelectedCategoryItem contains 2 elements in debugger mode, but then the last line in the constructor throws a:

System.ArgumentOutOfRangeException

Index was out of range. Must be non-negative and less than the size of the collection.

Parameter name: index

Of course, since this is Xamarin.Forms and VS for Mac, the error is thrown on the Main function, not at its actual location...

Am I doing something wrong, or is CollectionView just still buggy?

The issue was that I was creating new CategoryItem instances as the pre-selected ones, which is invalid, as they weren't by default the same instances that were in the CollectionView.ItemsSource property. I should have filtered the ItemsSource instances and put them as the pre-selected ones. Like this:

var alreadySelectedCategoryItems = alreadySelectedCategories.Select(pc => new CategoryItem { PlantCategory = pc, IsSelected = true }).Cast<object>();
SelectedCategoryItems = Categories
    .Where(sci => 
         alreadySelectedCategoryItems.Any(alreadySelected => 
              alreadySelected.PlantCategory.Id == sci.PlantCategory.Id);

So the items are selected off the ItemsSource itself and not created as new.

Although the error message was not as desired, so Xamarin.Forms team is going to fix that .

SelectedItems is read-only,you could not use like SelectedItems="{Binding SelectedCategoryItems}" in xaml 在此处输入图片说明

you could try to change in your behind code like:

CategoryColView.SelectedItems.Add(your selectItem 1);
CategoryColView.SelectedItems.Add(your selectItem 2);
CategoryColView.SelectedItems.Add(your selectItem 3);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM