xamarin / Xamarin.Forms

Xamarin.Forms is no longer supported. Migrate your apps to .NET MAUI.
https://aka.ms/xamarin-upgrade
Other
5.62k stars 1.87k forks source link

[Bug] Unable to select same item twice in a CollectionView #12491

Open snowman745 opened 4 years ago

snowman745 commented 4 years ago
  1. Create a CollectionView setting SelectionMode = Single
  2. Add SelectionChanged event.
  3. Add one item to the CollectionView
  4. Select the item firing the SelectionChanged event.
  5. Select the item again.

Result: SelectionChanged event not fired.

Note: I even set SelectedItem = null but this does not help.

private void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e) { FriendViewModel selectedItem = (FriendViewModel) FriendsCollectionView.SelectedItem; if(selectedItem != null) { ViewFriend(selectedItem.FriendId); FriendsCollectionView.SelectedItem = null; } }

Xamarin Forms version 4.8.0.1534 Visual Studio Version 16.7.5

NOTE: Repro'd on UWP, does NOT repro on Android.

Repro: CollectionViewSingleSelectionDemo.zip

rachelkang commented 4 years ago

Hi, @snowman745 - thanks for submitting this issue. The expected behavior for SelectionChanged is correct - it doesn't get fired if you select the same item twice since the selectedItem is already selected. The only way to fire SelectionChanged is to either (1) select a different item before selecting the item again, or (2) setting the selected item to null.

Try adding something like this in your SelectionChanged method instead: ((CollectionView)sender).SelectedItem = null; or consider using TapGestureRecognizer if that better suits your use case! (related docs here: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/gestures/tap)

Closing this issue, but if I misunderstood what's happening, please feel free to reopen with a sample project attached! Thanks :)

snowman745 commented 4 years ago

Hi, as stated in my repro, I am setting selectedItem to null.

This is what's broken.

I even tried it as you stated:

((CollectionView)sender).SelectedItem = null;

snowman745 commented 4 years ago

How do I reopen this?

rachelkang commented 4 years ago

@snowman745 Happy to keep looking at this! I followed the steps you described and was able to get it working with ((CollectionView)sender).SelectedItem = null;, and on the same version of XF as well. Could you attach a sample project that reproduces the issue, so that we can take a closer look at why it might not be working for you?

snowman745 commented 4 years ago

Can you try your project on UWP? It tried and it works as expected on Android.

If you cannot repro on UWP, ill upload a sample project.

Thanks.

alihut commented 3 years ago

Can you try your project on UWP? It tried and it works as expected on Android.

If you cannot repro on UWP, ill upload a sample project.

Thanks.

Same problem here. Works on Android, not on UWP.

snowman745 commented 3 years ago

Any update on this?

Agredo commented 3 years ago

Hi is there a workaround? Or any Updated?

everettpatel commented 2 years ago

Hi, I have the same problem! this is a real issue on UWP

AhmedAdelGadElkareeem commented 1 year ago

Hi, I have the same problem! this is a real issue on UWP

AhmedAdelGadElkareeem commented 1 year ago

I solve this bug using stacklayout bindable items source and set gesture tapped for item

<StackLayout BindableLayout.ItemsSource="{Binding User.TopFollowers}" Orientation="Horizontal" ...>

Mimisss commented 1 year ago

@snowman745 This still exists in Xamarin.Forms 5.0.0.2012. @rachelkang I guess this is expected behavior.

The real problem is that every damned web page out there suggests the code below:

private void MyCollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e.CurrentSelection != null)
    {
        MyObject item = (MyObject)e.CurrentSelection.FirstOrDefault();

        // do something with item

        // clear currently selected item to allow the same item to be selected again when user
        // navigates back to the page.
        ((CollectionView)sender).SelectedItem = null;
    }
}

Well, the above code causes the SelectionChanged event to fire again (since SelectedItem is changed programmatically) and the event handler to be called twice. And while the humble programmer thinks he/she is on the safe side since e.CurrentSelection is checked for null the ugly truth is that he/she isn't because for some reason known only by the ancient gods, e.CurrentSelection is NOT null the second time and the code breaks with a NullPointerException.

So, if one needs to set the selected item to null then one must double check for null, for example:

private void MyCollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e.CurrentSelection != null)
    {
        MyObject item = (MyObject)e.CurrentSelection.FirstOrDefault();

        // double check for null because this handler will be called twice (the second time
        // when SelectedItem is set to null BELOW) in which case e.CurrentSelection is NOT null
        if (item != null)
        {
            // do something useful with item
            ((CollectionView)sender).SelectedItem = null;
        }
    }
}

And that's all there is to it, really. Historically speaking, this exact same kind-of-control-behavior dates back to Visual Basic 6. Oh, well...