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... :|
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 ViewCell
s 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).
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"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With