Xamarin.forms: [UWP] Cannot de-select item in SelectionChanged handler

Created on 11 Dec 2019  路  8Comments  路  Source: xamarin/Xamarin.Forms

https://forums.xamarin.com/discussion/175532/how-to-deselect-item-in-collectionview#latest

Please check my report thread in xamarin forum above.

I don't know if my plan is applicable for the event "SelectionChanged", I want to spam the same item, I want to remove the SelectedItem immediately after clicking it. I already tried your solution but it didn't work on my case.

I have a productCollectionView which the inside controls was consist of (Image and labels). After you click an item it will automatic add in my cart so there's a time that you will spam a same item.

Here's my Xaml Code:

        <CollectionView x:Name="productCollectionView"
                        SelectionMode="Single"
                        ItemsSource="{Binding Products}"
                        ItemSizingStrategy="MeasureAllItems"
                        SelectionChanged="productCollectionView_SelectionChanged">
            <CollectionView.ItemsLayout>
                <GridItemsLayout Orientation="Vertical"
                                 Span="2"
                                 VerticalItemSpacing="5"/>
            </CollectionView.ItemsLayout>
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="12*"/>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <Image Source="{Binding Image}"
                               WidthRequest="50"
                               HeightRequest="50"
                               Grid.Row="0"/>

                        <StackLayout Grid.Row="1"
                                     Orientation="Vertical"
                                     VerticalOptions="Start"
                                     HorizontalOptions="Center">
                            <Label Text="{Binding Name}"
                                   FontSize="Medium"/>
                        </StackLayout>

                        <StackLayout Grid.Row="2"
                                     Orientation="Vertical"
                                     VerticalOptions="Start"
                                     HorizontalOptions="Center">
                            <Label Text="{Binding Price}"
                                   FontSize="Small"
                                   FontAttributes="Bold"/>
                        </StackLayout>
                    </Grid>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

Here's my Code Behind for my SelectionChanged event:

private void productCollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var selectedList = e.CurrentSelection;

    foreach (var selected in selectedList)
    {
        _guestViewModel.AddProductToOrderListCommand((ProductViewModel)selected);
    }
    SwitchToOrderDetailGrid();

    ((CollectionView)sender).SelectedItem = null;
}

Here's the picture of my sample problem, I've clicked the product Matcha Milk Tea then there's a line on item after clicking it and I think that's the indicator of selected item for my productCollectionView. After clicking the Matcha Milk Tea the event will triggered but after re-click the same item the event will not trigger. Hope you to understand me :(

  • Version with issue: Xamarin 4.3.0.991221 (Latest)
  • Last known good version: Xamarin 4.3.0.991221 (Latest)
  • IDE: Visual Studio 2019 Enterprise
  • Platform Target Frameworks:

    • Android: 9.0

    • UWP: 17763

  • Nuget Packages: EF Core , EF Core.Tools , MySql.Data.EntityFrameworkCore

Capture

collectionview 3 bug

Most helpful comment

I can't get this Task.Delay workaround to actually work. Once I do that in the SelectionChanged handler, it will never fire again. Ditto SelectedChangedCommand.

Clicking on CollectionView items does "select" items visually, they get a border.

6158 also confirms that nothing works.

All of this is caused by #5781, which is desperately required.

All 8 comments

_8842 Repro.zip

On UWP, setting the SelectedItem to null in the SelectionChanged handler is not updating the native selection. It's working correctly on Android.

@salaritangianbonfire To answer your question - you've found a bug. What you're doing should work as expected.

The way I got around this is to do...

Task.Run(async ()=> { await Task.Delay(100); ((CollectionView)sender).SelectedItem = null; });

I can't get this Task.Delay workaround to actually work. Once I do that in the SelectionChanged handler, it will never fire again. Ditto SelectedChangedCommand.

Clicking on CollectionView items does "select" items visually, they get a border.

6158 also confirms that nothing works.

All of this is caused by #5781, which is desperately required.

A workaround might be to attach a TapGestureRecognizer to the DataTemplate. It seems to be working for me.

A workaround might be to attach a TapGestureRecognizer to the DataTemplate. It seems to be working for me.

but it seems not works for android.
https://github.com/xamarin/Xamarin.Forms/issues/5781#issuecomment-559918758

@bill2004158 I'm using Android. Might have been another issue that was fixed since then?

My workaround was similar to @BioTurboNick but I tied my GestureRecognizer to the layout inside the DataTemplate.

Needed to set the command parameter's binding context to the content page in order to reference command in view model.
Works for me in Android and Ios.

Hope this helps somone.

Code sample below:

<ContentPage.Content>
    <StackLayout>

        <CollectionView 
    ItemsSource="{Binding MyCollection}" >

            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Frame>
                        <StackLayout>

                            <StackLayout.GestureRecognizers>

                                <TapGestureRecognizer  Command="{Binding BindingContext.MyCommandInViewModel, 
                                     Source={x:Reference MyContentPage}}" CommandParameter="{Binding .}" 
                                     NumberOfTapsRequired="1"/>  

            </StackLayout.GestureRecognizers>

                Item Content goes here..........

                        </StackLayout>
                    </Frame>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
</StackLayout>
</ContentPage.Content>

Was this page helpful?
0 / 5 - 0 ratings