TimeTravelPenguin
TimeTravelPenguin

Reputation: 340

GestureRecognizer not working on CollectionView with DataTemplate

I am playing around in Xamarin with GestureRecognizers, and I have the following code:

<CollectionView
  Grid.Row="0"
  EmptyView="No player information"
  ItemsSource="{Binding Voices, Mode=OneWay}">

  <CollectionView.GestureRecognizers>
    <TapGestureRecognizer
      Command="{Binding CommandPlayerTapped}"
      CommandParameter="hi"
      NumberOfTapsRequired="1" />
  </CollectionView.GestureRecognizers>

  <CollectionView.ItemTemplate>
    <DataTemplate>

      <StackLayout>
        <views:PancakeItemView Margin="5" BorderColor="Black">
          <views:VoiceInfoContainerView Style="{StaticResource VoiceDisplayStyle}" />
        </views:PancakeItemView>
      </StackLayout>

    </DataTemplate>
  </CollectionView.ItemTemplate>
</CollectionView>

My TapGestureRecognizer is bound to a simple Command that makes a popup message; nothing complex. The DataTemplate is a PancakeView wrapping a simple view to show some names like shown here:

Screenshot showing View

Again, this is nothing complex, however, I feel this may be where the problem lies, as I cannot find any other information online.

I have tried putting the gesture code in other elements, with no success. Any ideas as to why tappingthese views fails to trigger the command?

Upvotes: 1

Views: 4895

Answers (1)

Ricardo Dias Morais
Ricardo Dias Morais

Reputation: 2087

CollectionView has a property for the SelectedItem

SelectionMode="Single"
SelectedItem="{Binding SelectedVoice}"

And then on your ViewModel:

private Voice _selectedVoice; //I don't know what type of items is your Collection Voices, so i'm using Voice here
public Voice SelectedVoice
{
    get { return _selectedVoice; }
    set { 
          _selectedVoice = value; 
          CommandPlayerTapped.Execute();
        }
}


...

//On the function that CommandPlayerTapped called:

if(SelectedVoice != null)
{
    //Your code
}
else{
    //The Item was deselected
}

Here is a little extra on the way you were trying previously and why it didn't work:

If you are trying to set an GestureRecognizer for each item in your CollectionView, you are using it in the wrong place, you are setting the GR in the Collection Itself, not in each item.

You need to pass the correct BindingContext, your item's have the Voices ItemSource BindingContext, but you need the ViewModel Context instead, you can reference a diferent Context (eg: the CollectionView itself),

First make your CollectionView reference by adding x:Name="CollectionViewForBinding" for example:

<CollectionView
  x:Name="CollectionViewForBinding"
  Grid.Row="0"
  EmptyView="No player information"
  ItemsSource="{Binding Voices, Mode=OneWay}">

And then you reference the BindingContext Like This:

<StackLayout>
    <StackLayout.GestureRecognizers>
          <TapGestureRecognizer
              Command="{Binding BindingContext.CommandPlayerTapped, Source={x:Reference Name=CollectionViewForBinding}}"
              CommandParameter="{Binding ThePropertyOfTheItemYouWantToPass}"
              NumberOfTapsRequired="1" />
    </StackLayout.GestureRecognizers>
    <views:PancakeItemView Margin="5" BorderColor="Black">
        <views:VoiceInfoContainerView Style="{StaticResource VoiceDisplayStyle}" />
    </views:PancakeItemView>
</StackLayout>

Upvotes: 8

Related Questions