无法在 iOS 的 Xamarin.Forms 的 CollectionView 中重新选择之前选择的项目

Cant reselect previous selected item in CollectionView in Xamarin.Forms on iOS

TLDR

CollectionView 在 iOS 中损坏,无法在线找到任何解决方案。 Google fu 或只是没有看到答案。

问题

我有一个 CollectionView(我们称之为 A),其中包含的项目只是字符串值,用于在不同的 CollectionView(我们称之为 B)上进行过滤,其中包含 selectCollectionView A 中过滤选项的结果.

我在 CollectionView A 中有 3 个不同的筛选选项:“全部”、“靠近你”、“在线”。

问题是在 iOS 上,当我 select 例如第一次在页面上的 CollectionView A 中过滤选项“All”时,它会进行过滤并在 CollectionView B 中显示结果,例如,当我在 CollectionView A 中选择过滤选项“在线”时,它会过滤并在 CollectionView B 中显示结果。

但是当我在 CollectionView A 中第二次选择过滤选项“全部”时,它没有响应,没有事件触发,没有命令运行,也没有被禁用。它只是显示,但我不能用它做任何事情。

预期结果

可以重新select iOS 上的前一项,在Android 没问题。

实际结果

无法重新select iOS 上的上一个项目,需要返回堆栈中的上一页,然后导航回页面以重置过滤。

xaml 标记

如上所述,这是 CollectionView A 的 xaml 标记,唯一包含要过滤的字符串值。

<CollectionView ItemsSource="{Binding FilterLocations}"
                Grid.Row="2"
                SelectedItem="{Binding SelectedFilterLocation}"
                SelectionMode="Single"
                HeightRequest="50">
   <CollectionView.ItemsLayout>
      <LinearItemsLayout Orientation="Horizontal"
                         ItemSpacing="10" />
   </CollectionView.ItemsLayout>
      <CollectionView.ItemTemplate>
         <DataTemplate x:DataType="x:String">
            <StackLayout xct:TouchEffect.NativeAnimation="True">
               <Frame BorderColor="{StaticResource BorderColor}"
                      x:Name="subCategoryFrame"
                      Padding="14, 10">
                  <Label Text="{Binding .}"
                         x:Name="subCategoryName"
                         FontFamily="{StaticResource FontPoppinsLight}"
                         TextColor="{StaticResource PrimaryAlt}" />
               </Frame>
            </StackLayout>
         </DataTemplate>
      </CollectionView.ItemTemplate>
         <CollectionView.Header>
            <BoxView WidthRequest="0"
                     HeightRequest="1"
                     BackgroundColor="Transparent" />
         </CollectionView.Header>
         <CollectionView.Footer>
            <BoxView WidthRequest="{StaticResource NormalSpacingDouble}"
                     HeightRequest="1"
                     BackgroundColor="Transparent" />
         </CollectionView.Footer>
      </CollectionView>

CollectionView A 在 SelectionMode:Single 中,SelectedItem 绑定到其绑定的 ViewModel 上的 ICommand。在 ViewModel 中,CollectionView A 中的项目的 selection 将触发 CollectionView B 中的过滤

到目前为止我做了什么

我的设置是,如果 CollectionView A 中的某个项目被禁用,它会变成红色,但不会变成红色。

我曾尝试在后面的代码中添加一个事件,尝试将 SelectedItem 设置为 null,但该事件被触发并使所有事件发生两次,一次用于 select 显示屏幕上的项目第二个用于更改后面代码中的 SelectedItem。

代码:

private void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
      if (Device.RuntimePlatform == Device.iOS)
      {
         var collectionView = sender as CollectionView;
         if (collectionView == null) return;

         if (collectionView.SelectedItem != null)
         {
             collectionView.SelectedItem = null;
         }
      }
}

(我知道在 Code Behind 中做非设计逻辑的逻辑内容是一个很大的禁忌,但由于时间压力,我需要解决这个问题或快速修复。)

对不起文字墙

使用 TapGestureRecognizer.

下面,MyItemCommand 是在MyViewModel中定义的,{Binding .}是指在ItemsSource中选择的项目。

<DataTemplate ...>
  <StackLayout>
    <StackLayout.GestureRecognizers>
      <TapGestureRecognizer Command="{Binding Source={RelativeSource AncestorType={x:Type vm:MyViewModel}},
                                              Path=MyItemCommand}"
                            CommandParameter="{Binding .}"/>
    </StackLayout.GestureRecognizers>
    ...

首先将collection view绑定到事件selectionchange中。

<CollectionView ItemsSource="{Binding FilterLocations}"
                Grid.Row="2"
                SelectedItem="{Binding SelectedFilterLocation}"
                SelectionMode="Single"
                HeightRequest="50"
                SelectionChanged="collection_SelectionChanged">

然后在事件中将所选项目置为空。

private async void collection_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
   try
   {
      var Sender = sender as CollectionView;
      if (Sender.SelectedItem == null)
          return;
                
       Sender.SelectedItem = null;
    }
    catch (Exception ex)
    {

     }
}