John Livermore
John Livermore

Reputation: 31313

Xamarin Forms CollectionView TapGestureRecognizer not firing on label

I have a XF app with the following collection view defined. The 2nd label has a TapGestureRecognizer that doesn't fire DoSomethingInteresting in the model when I tap the label (trying this on Android). Can someone see what the issue is please?

A working sample can be cloned from here.

XAML

<?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:local="clr-namespace:SampleApp"
                 x:Class="SampleApp.MainPage">

        <StackLayout>
            <CollectionView ItemsSource="{Binding GaugeSites}">
                <CollectionView.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="40" />
                            </Grid.RowDefinitions>

                            <Label Grid.Column="0"
                                   Text="{Binding Description}"
                                   FontSize="20"
                                   Margin="10"
                                   TextColor="Black"
                                   FontAttributes="Bold" />

                            <Label Grid.Column="1" 
                                   Margin="10"
                                   FontSize="20" 
                                   Text="Click Me!">
                                <Label.GestureRecognizers>
                                    <TapGestureRecognizer Command="{Binding DoSomethingInteresting}" />
                                </Label.GestureRecognizers>
                            </Label>
                        </Grid>
                    </DataTemplate>
                </CollectionView.ItemTemplate>

            </CollectionView>
        </StackLayout>
    </ContentPage>

Model

namespace SampleApp
{
    public class MainPageModel : FreshBasePageModel
    {
        public MainPageModel() : base()
        {
            GaugeSites = new List<GaugeSite>();

            for (var index = 1; index <= 5; index++)
            {
                GaugeSites.Add(new GaugeSite()
                {
                    Description = $"Gauge Site {index}"
                });
            }
        }

        public List<GaugeSite> GaugeSites { get; set; }

        public Command DoSomethingInteresting
        {
            get
            {
                return new Command(() =>
                {

                });
            }
        }
    }

    [AddINotifyPropertyChangedInterface]
    public class GaugeSite
    {
        public string Description { get; set; }
    }
}

Upvotes: 2

Views: 6955

Answers (2)

Mouse On Mars
Mouse On Mars

Reputation: 1132

Maybe this is redundant but I will take my chances. As other answers indicated you need to set the source within your TapGestureRecognizer to the name of the CollectionView. However, it is probably useful to know which GaugeSite instance was associated with the CollectionView item whose TabGestureRecognizer was tapped. To add this info add a CommandParamter, i.e.

    <Label.GestureRecognizers>
        <TapGestureRecognizer Command="{Binding BindingContext.DoSomethingInteresting, 
                              CommandParameter="{Binding}"
                              Source={x:Reference YourCollectionName}}" />
    </Label.GestureRecognizers>

When it comes to the command you could use

DoSomethingInteresting = new Command<GaugeSite>((a) => DoSomething(a));

in your viewmodels contructor. And the method referenced by the lambda would be

void DoSomething(GaugeSite gaugeSite)
{
   // ....
}

Hope this helps

Upvotes: 3

Cherry Bu - MSFT
Cherry Bu - MSFT

Reputation: 10346

I have download your sample, please take a look the following step.

1.Binding MainpageModel for MainPage bindingContext, add this line in MainPage.cs.

 this.BindingContext = new MainPageModel();

2.Name Collectionview as collection1, then modify label command.

 <CollectionView x:Name="collection1" ItemsSource="{Binding GaugeSites}">
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="40" />
                    </Grid.RowDefinitions>

                    <Label
                        Grid.Column="0"
                        Margin="10"
                        FontAttributes="Bold"
                        FontSize="20"
                        Text="{Binding Description}"
                        TextColor="Black" />

                    <Label
                        Grid.Column="1"
                        Margin="10"
                        FontSize="20"
                        Text="Click Me!">
                        <Label.GestureRecognizers>
                            <TapGestureRecognizer Command="{Binding BindingContext.DoSomethingInteresting, Source={x:Reference collection1}}" />
                        </Label.GestureRecognizers>
                    </Label>
                </Grid>
            </DataTemplate>
        </CollectionView.ItemTemplate>

    </CollectionView>

Then you can try again.

Upvotes: 3

Related Questions