Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GestureRecognizers does not work inside a ListView

I have a ListView as follows

<ListView
        Grid.Row="0"
        Margin="0"
        x:Name="ItemsListView"
        ItemsSource="{Binding SourceItems}"
        VerticalOptions="FillAndExpand"
        HasUnevenRows="false"
        RefreshCommand="{Binding LoadItemsCommand}"
        IsPullToRefreshEnabled="true"
        IsRefreshing="{Binding IsBusy}"
        ItemSelected="OnItemSelected"
        IsVisible="{Binding ShowListView}"
        RowHeight="55">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <Grid
                        Margin="15,0,0,0"
                        Padding="0"
                        RowSpacing="0"
                        ColumnSpacing="0">
                        <Grid.RowDefinitions>
                            <RowDefinition
                                Height="*" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition
                                Width="1*" />
                            <ColumnDefinition
                                Width="7*" />
                            <ColumnDefinition
                                Width="1*" />
                            <ColumnDefinition
                                Width="1*" />
                        </Grid.ColumnDefinitions>
                        <Image
                            VerticalOptions="CenterAndExpand"
                            HorizontalOptions="CenterAndExpand"
                            HeightRequest="35"
                            WidthRequest="35"
                            Grid.Row="0"
                            Grid.Column="0"
                            Aspect="AspectFit"
                            Source="{Binding Icon}">
                        </Image>
                        <StackLayout
                            VerticalOptions="CenterAndExpand"
                            Spacing="0"
                            CompressedLayout.IsHeadless="true"
                            Margin="15,0,0,0"
                            Grid.Row="0"
                            Grid.Column="1">
                            <Label
                                VerticalTextAlignment="Start"
                                Text="{Binding Name}"
                                FontAttributes="Bold"
                                LineBreakMode="NoWrap"
                                Style="{DynamicResource ListItemTextStyle}"
                                FontSize="16" />
                            <Label
                                VerticalTextAlignment="Start"
                                Text="{Binding Description}"
                                LineBreakMode="NoWrap"
                                Style="{DynamicResource ListItemDetailTextStyle}"
                                FontSize="13" />
                        </StackLayout>
                        <Image
                            Grid.Row="0"
                            Grid.Column="3"
                            HeightRequest="20"
                            WidthRequest="20"
                            VerticalOptions="CenterAndExpand"
                            HorizontalOptions="StartAndExpand"
                            Aspect="AspectFit"
                            Source="{Binding Icon}" />
                        <Image
                            BackgroundColor="Lime"
                            Grid.Row="0"
                            Grid.Column="2"
                            InputTransparent="false"
                            Margin="0,0,10,0"
                            HeightRequest="20"
                            WidthRequest="20"
                            VerticalOptions="CenterAndExpand"
                            HorizontalOptions="StartAndExpand"
                            Aspect="AspectFit"
                            Source="ic_two">
                            <Image.GestureRecognizers>
                                <TapGestureRecognizer
                                    Command="{Binding OnFavouriteCommand}"
                                    CommandParameter="{Binding .}"
                                    NumberOfTapsRequired="1">
                                </TapGestureRecognizer>
                            </Image.GestureRecognizers>
                        </Image>
                    </Grid>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

and in my ViewModel I have

public ICommand OnFavouriteCommand { get; set; }

public MyViewModel()
{           
  OnFavouriteCommand = new Command<Object>(OnFavourite);
}

void OnFavourite(Object ob)
{
  Debug.WriteLine(ob);
}

I don't get a Break Point hit on OnFavourite. I can't figure out what am I missing here? The idea was to get a gesture recognizers attached to each image and pass down the item bound to that row only.

I've just noticed, if I bring

<Image
            BackgroundColor="Lime"
            Grid.Row="1"
            InputTransparent="false"
            Margin="0,0,10,0"
            HeightRequest="20"
            WidthRequest="20"
            VerticalOptions="CenterAndExpand"
            HorizontalOptions="StartAndExpand"
            Aspect="AspectFit"
            Source="ic_favourites">
            <Image.GestureRecognizers>
                <TapGestureRecognizer
                    Command="{Binding OnFavouriteCommand}"
                    CommandParameter="{Binding .}"
                    NumberOfTapsRequired="1">
                </TapGestureRecognizer>
            </Image.GestureRecognizers>
        </Image>

Out side of the ListView the break point does get hit!. Left me scratching my head... :|

like image 875
envyM6 Avatar asked Apr 15 '18 13:04

envyM6


2 Answers

While what Adit wrote is true, let me give you some background. Within the DataTemplate, the BindingContext of the cells (and hence the children of them) are not set to the BindingContext of the parent (i.e. the ListView), but for each element from your ListView.ItemSource a cell is created and its BindingContext is set to that element. Otherwise you would not be able to bind the properties of the ViewCells children to your fields like Icon, Name, Description, etc.

In WPF there is the possibility to bind to the parents DataContext (see here), but AFAIK this is not possible in Xamarin.Forms (see here). Therefor you'll have to reference the parent explicitly, i.e. assign a name via x:Name="Page" (or whatever name you'd like to give it) and then reference it via the Source property in your binding

Command="{Binding Path=BindingContext.OnFavouriteCommand,Source={x:Reference Page}}"

Since you set the binding source not the the BindingContext of Page, but to Page, you'll have to add the BindingContex to the path. Furthermore, in order to pass the element that is represented by the current cell, to the command, you'll have to set

CommandParameter="{Binding .}"

which binds CommandParameter to the element that is referenced by the cell (which you already did).

like image 196
Paul Kertscher Avatar answered Nov 06 '22 12:11

Paul Kertscher


To work gesture in listview use like this

<Image
    BackgroundColor="Lime"
    Grid.Row="1"
    InputTransparent="false"
    Margin="0,0,10,0"
    HeightRequest="20"
    WidthRequest="20"
    VerticalOptions="CenterAndExpand"
    HorizontalOptions="StartAndExpand"
    Aspect="AspectFit"
    Source="ic_favourites">
    <Image.GestureRecognizers>
        <TapGestureRecognizer
            Command="{Binding Binding Path=BindingContext.OnFavouriteCommand,Source={x:Reference root}}"
            CommandParameter="{Binding .}"
            NumberOfTapsRequired="1">
        </TapGestureRecognizer>
    </Image.GestureRecognizers>
</Image>

Here root will be page name like set X:Name of your page be root like x:Name="root"

like image 6
Adit Kothari Avatar answered Nov 06 '22 12:11

Adit Kothari