maui icon indicating copy to clipboard operation
maui copied to clipboard

Cannot preselect items in CollectionView when it's multiselect on Windows, iOS and macOS

Open KeithBoynton opened this issue 1 year ago • 11 comments

Description

Using a CollectionView it is not possible to preselect items when mode is set to "multiple". It doesn't work on Windows, iOS or macOS however it does work on Android.

Using the method described here: https://learn.microsoft.com/en-us/dotnet/maui/user-interface/controls/collectionview/selection#multiple-preselection Multiple preselection does not work.

No items in the collection view are pre selected even though the collection in the view model does have the correct values.

I cannot find a way to preselect items in the CollectionView on Windows, iOS or macOS. The only way I can find to select items programmatically from the view model is by using the UpdateSelectedItems method and that only seems to work when triggered manually from a button. It does not work in the constructor or even when used in the onAppearing method.

Steps to Reproduce

  1. Follow the steps described in the following article to set up a collection view and populate it with preselection in a view model https://learn.microsoft.com/en-us/dotnet/maui/user-interface/controls/collectionview/selection#multiple-preselection
  2. Run the solution and observe the items are not pre selected on Windows, iOS or macOS. However they are preselected on Android.

Use the attached example solution.

  1. Run the solution.
  2. Observe that the items are not pre-selected when the app is first executed, on Windows, iOS and macOS.
  3. Click the button labelled "Select using Binding" and observe the items are NOT selected.
  4. Click the button labelled "Select using Method" and observe the items ARE selected.

Link to public reproduction project repository

https://github.com/KeithBoynton/CollectionView

Version with bug

7.0.49

Last version that worked well

Unknown/Other

Affected platforms

iOS, Windows, macOS

Affected platform versions

Latest

Did you find any workaround?

No

Relevant log output

No response

KeithBoynton avatar Jun 18 '23 18:06 KeithBoynton

I think the issue you're seeing is partially due to an MAUI bug and vaguely worded documentation leading to your code that doesn't work correctly. I've created a repro project showing this: https://github.com/drasticactions/MauiRepros/blob/main/CollectionView/

https://github.com/KeithBoynton/CollectionView/blob/master/ViewModel.cs#L35-L48

You've implemented INotifyPropertyChanged on your view model and directly set the SelectedItems binding to a new ObservableCollection. But this itself doesn't (or shouldn't) do anything. If setting items directly, you must invoke the PropertyChanged event so the UI can update.

https://github.com/drasticactions/MauiRepros/blob/main/CollectionView/ViewModel.cs#L48-L49

Either this or you can change your code to directly update the ObservableCollection list instead of setting it; since then, those events are handled by the UI so it can update.

        [RelayCommand]
        Task PreSelectUsingBinding()
        {
            SelectedItems.Clear();
            SelectedItems.Add(Items[1]);
            SelectedItems.Add(Items[3]);

            return Task.CompletedTask;
        }

Doing either of these things would fix your "binding" code, the docs imply that "setting" the binding to something else or null would clear it, (https://learn.microsoft.com/en-us/dotnet/maui/user-interface/controls/collectionview/selection#clear-selections) that that's "true", but only if you fully wire in INotifyPropertyChanged, which the page doesn't show. If this works on Android without doing that, then that seems more like the bug than the other way around.

That said, there does seem to be an issue, at least with WinUI, where it doesn't auto-set the SelectedItems in the CollectionView even when it is set when the binding was created. Unless I'm missing something else, that should be working and it's not.

@mattleibow @PureWeen Do ya'll have thoughts on this?

drasticactions avatar Jun 19 '23 03:06 drasticactions

Hi @KeithBoynton. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

ghost avatar Jun 19 '23 03:06 ghost

Yes @drasticactions thats a good catch and is definitely a miss on the documentation too. I've updated the code for that and yes the "binding" button does now work. However, the original issue still remains.

I cannot preselect the items on the collectionview without manual intervention, ie. getting the user to click a button...

  1. Setting SelectedItems in the constructor does not update the UI
  2. Setting SelectedItems or updating the existing SelectedItems collection via the OnAppearing override does not update the UI

I've updated the linked repo, where you can see it not working via the constructor or a call in the OnAppearing method

KeithBoynton avatar Jun 19 '23 07:06 KeithBoynton

I can confirm there are issues with CollectionView preselected items on iOS and Windows. Android works fine. Even if everything is done correctly with SelectedItems / UpdateSelectedItems.

  • Windows: don't work at all
  • iOS: partly works - items are actually selected, but it isn't shown visually. If a user selects another item the preselected items will suddenly appear as selected.

espenrl avatar Jun 19 '23 08:06 espenrl

Lets not forget macOS too please.

KeithBoynton avatar Jun 19 '23 12:06 KeithBoynton

I can confirm there are issues with CollectionView preselected items on iOS and Windows. Android works fine. Even if everything is done correctly with SelectedItems / UpdateSelectedItems.

  • Windows: don't work at all
  • iOS: partly works - items are actually selected, but it isn't shown visually. If a user selects another item the preselected items will suddenly appear as selected.

I have noticed that the issue is related to VisualStates (Windows). I managed to access the item's visual element and set the visual state manually using VisualStateManager, and it works fine. However, this approach is not intended to be used in production applications. Hope this help isolate the issue.

jesusj90 avatar Jul 18 '23 10:07 jesusj90

This is serious issue for us. We have lots of popup menus on Windows which require preselected items. Would be great if it gets some attention.

Vroomer avatar Aug 07 '23 10:08 Vroomer

Mentioning here also that if SelectionMode is set to Multiple, and you try to highlight multiple items with UpdateSelectedItems, then I find on iOS that the items aren't displayed at all!!!

jeremy-visionaid avatar Dec 28 '23 20:12 jeremy-visionaid

On iOS the selected items logic is tied with the UI elements and I found that it helps setting selected items after the list is loaded into the UI.

espenrl avatar Dec 28 '23 20:12 espenrl

Verified this issue with Visual Studio Enterprise 17.9.0 Preview 4. Can repro on Windows platforms with sample project. https://github.com/KeithBoynton/CollectionView

jaosnz-rep avatar Jan 26 '24 07:01 jaosnz-rep

I can not have preselected items in a CollectionView on iOs either. VisualStates are ignored until another item is selected. If anybody has a workaround it would be much appreciated. :)

BeepBeepBopBop avatar Jan 27 '24 17:01 BeepBeepBopBop

I can confirm the issues for our project as well. We're building a MAUI App for Windows. We added a CollectionView with SelectionMode Multiple and the preselection of the items selected by the user does not work if we use a custom style for the elements in the CollectionView. The preselection is not applied for the elements which are chosen beforehand. However if the user clicks an item the UI gets updated.

It works using the default style for selected items which is provided by the CollectionView but this style is not visible enough to provide a good user experience and sadly we found no way to customize the default styling. It seems like it is only possible to overwrite it with a custom style.

It would be great and highly appreciated if someone of the developers can look into this issue @mattleibow

Julianfes avatar Jan 29 '24 12:01 Julianfes

Can you try the Loaded event on the CollectionView to select things? I wonder if some platforms need the list to actually be in the layout and on screen...

mattleibow avatar Jan 30 '24 16:01 mattleibow

Can you try the Loaded event on the CollectionView to select things? I wonder if some platforms need the list to actually be in the layout and on screen...

That's my experience with iOS.

espenrl avatar Jan 30 '24 16:01 espenrl

The CollectionView in our project is embedded in a ContentView which is used as a input mask for the user to put in Data in Entry fields. The ContentView is embedded in a ContentPage. The Loaded Event of the CollectionView itself gets only triggered once in initial loading of the page. If the ContentView opens the Loaded event of the CollectionView does not get triggered.

Julianfes avatar Feb 02 '24 11:02 Julianfes

I seem to be having this issue on Android.

Quaybe avatar Apr 30 '24 15:04 Quaybe

The workaround with the Loaded event for the CollectionView works for me on iOS. I did not test it on Android yet. Just add the event handler in the constructor of the page. When the loaded event triggers manually set the SelectedItems of the collection from the viewmodel.

It is hacky but at least it works.

public SelectionPage(SelectionViewModel viewModel)
{
    InitializeComponent();
    _viewModel = viewModel;
    BindingContext = viewModel;

    ItemCollection.Loaded += ItemCollection_Loaded;
}

private void ItemCollection_Loaded(object? sender, EventArgs e)
{
    ItemCollection.SelectedItems = _viewModel.SelectedItems;
}

OneBitAndy avatar May 29 '24 12:05 OneBitAndy

This code reapplies selection on load. CollectionView.Loaded += OnCollectionViewLoaded;

private void OnCollectionViewLoaded(object? _, EventArgs __)
{
    // ISSUE: Workaround for bug where the CollectionView doesn't set initial selection

    if (CollectionView.SelectionMode == SelectionMode.Single)
    {
        var selectedItem = CollectionView.SelectedItem;
        CollectionView.SelectedItem = null;
        CollectionView.SelectedItem = selectedItem;
    }
    else if (CollectionView.SelectionMode == SelectionMode.Multiple)
    {
        var selectedItems = CollectionView.SelectedItems;
        CollectionView.SelectedItems = null;
        CollectionView.SelectedItems = selectedItems;
    }
}

espenrl avatar May 29 '24 14:05 espenrl

This issue is really bad and it doesn't seem to have any workaround for Windows.

I tried reseting the source multiple times and delay it with TaskCompletionSource after the the VM loads SelectedItems, but nothing works.

    private async void collectionView_Loaded(object sender, EventArgs e)
    {
        await vm.TCS.Task;

        collectionView.ItemsSource = null;
        collectionView.SelectedItems = null;
        collectionView.SetBinding(CollectionView.ItemsSourceProperty, "ItemGroups");
        collectionView.SetBinding(CollectionView.SelectedItemsProperty, "SelectedItems");

        collectionView.SelectedItems = null;
        collectionView.SetBinding(CollectionView.SelectedItemsProperty, "SelectedItems");

        //collectionView.SelectedItems = vm.SelectedItems;
        //collectionView.UpdateSelectedItems(vm.SelectedItems);
    }

Given that CollectionView generates Item views with DataTemplate, I don't see any way to manually update VisualState of each Item either.

Vroomer avatar Jun 23 '24 10:06 Vroomer

I am waiting for a solution more than 15 Month. Meanwhile i am using the sfListView from Syncfusion. You can preselect multiple items, like in collectionview you have to handle them as OberservableCollection. SfListview should only be used in Singleton Pages, because it prevents the page from being garbage collected. So this is also not a solution for me to deploy. CollectionView ist Mauis number one manpower burning feature. Waiting ....

update: it seems, syncfusion has fixed the sfListView garbage collection problem. Pages with that control are correctly disposed now. Don't know how long it's fixed because i gave up checking memory leaks months ago. All my pages and viewmodels, expect shell root's pages, are destructed now.

JoeVoo avatar Jun 23 '24 13:06 JoeVoo

Hello, I just want to add a precision: the behavior of preselection is also buggy when SelectionMode is set to Single. On Windows, upon CollectionView loading, the selected item is systematically set to null.

BeepBeepBopBop avatar Jul 06 '24 07:07 BeepBeepBopBop

It seems that many things broke since MAUI release. Xamarin is now out of support, MS is just pushing us to React Native and Flutter. I've faced so many serious issues the last few months... I have 20 years of experience and never ever before have come across so many issues. Just at the top of my head:

  1. CollectionView selection is broken
  2. CarouselView SnapPointsType is not working properly, some time the view snaps to the center some times is off.
  3. CarouselView VisualStateGroup not working on iOS
  4. CarourselView SelectedItem not updating
  5. Button gradient spills outside the control
  6. Maps control seems to re-render the same markers when the Itemsource is set. and the list goes on

kaniosm avatar Aug 12 '24 17:08 kaniosm