Touch detection on a label, inside ViewCell, inside ListView

I am trying to handle something similar (from a user interface perspective) so that: enter image description here

to invoke two different business logic for:

  • tapping on the ViewCell element itself (inside the ListView) - in the example, go to another page
  • clicking on the Label element ( Clickable Label ), which is located inside the specified ViewCell element - in the example, delete this object or smth else

I would like to have a whole β€œtapping” logic inside the ViewModel page.

Based on the Xamarin forum, I can cause some logic to β€œclick” my action to remove from the cell, however, right inside my data model, which in my software is not a good solution, since I would like to manipulate the List (so the most preferred way was would have this logic on the ViewModel page).

What I have right now:

My View XAML Code page is as follows:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App.Views.TestView"> <ContentPage.Content> <StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"> <ListView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" ItemsSource="{Binding MyItemsCollection}" SelectedItem="{Binding SelectedItem}"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout Orientation="Horizontal"> <!-- Name Label --> <Label Text="{Binding Name}" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" /> <!-- Delete "Icon" --> <Label Text="Clickable Label" VerticalOptions="CenterAndExpand" HorizontalOptions="EndAndExpand"> <Label.GestureRecognizers> <TapGestureRecognizer Command="{Binding OnClickableLabel}" CommandParameter="{Binding .}" /> </Label.GestureRecognizers> </Label> </StackLayout> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </ContentPage.Content> </ContentPage> 

My View C # code page looks (and not specific code there, except for binding ** BindingContext * to the ViewModel page):

 public partial class TestView : ContentPage { public TestView() { InitializeComponent(); BindingContext = ServiceLocator.Current.GetInstance<TestViewModel>(); } } 

My page C # ViewModel Code is as follows:

 public class TestViewModel : ViewModelBase { public TestViewModel() { MyItemsCollection = GetMyItemsCollection(); } private List<MyItem> GetMyItemsCollection() { return new List<MyItem> { new MyItem { ID = 1L, Name = "Item 1 Name" }, new MyItem { ID = 2L, Name = "Item 2 Name" }, new MyItem { ID = 3L, Name = "Item 3 Name" } }; } private List<MyItem> _myItemsCollection { get; set; } public List<MyItem> MyItemsCollection { get { return _myItemsCollection; } set { _myItemsCollection = value; RaisePropertyChanged(); } } private MyItem _SelectedItem { get; set; } public MyItem SelectedItem { get { return _SelectedItem; } set { if (_SelectedItem != value) { _SelectedItem = value; RaisePropertyChanged(); Debug.WriteLine("SelectedItem: " + _SelectedItem.Name); } } } private RelayCommand<object> _OnClickableLabel; public RelayCommand<object> OnClickableLabel { get { return _OnClickableLabel ?? (_OnClickableLabel = new RelayCommand<object>((currentObject) => Test(currentObject))); } } private void Test(object currentObject) { Debug.WriteLine("This should work... but it not working :("); } } 

My model code as follows:

 public class MyItem { public long ID { get; set; } public string Name { get; set; } private RelayCommand<object> _OnClickableLabel; public RelayCommand<object> OnClickableLabel { get { return _OnClickableLabel ?? (_OnClickableLabel = new RelayCommand<object>((currentObject) => Test(currentObject))); } } private void Test(object currentObject) { Debug.WriteLine("This works... but it not good idea, to have it here..."); } } 

Any idea what needs to be changed to call OnClickableLabel directly on my ViewModel page? I know this is something wrong:

 <TapGestureRecognizer Command="{Binding OnClickableLabel}" CommandParameter="{Binding .}" /> 

but I don’t know what: /.

Help! Many thanks.

+6
source share
1 answer

Ok, I found a solution by extending the XAML code:

 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="App.Views.TestView" x:Name="Page"> <ContentPage.Content> <StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"> <ListView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" ItemsSource="{Binding MyItemsCollection}" SelectedItem="{Binding SelectedItem}"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout Orientation="Horizontal"> <!-- Name Label --> <Label Text="{Binding Name}" VerticalOptions="CenterAndExpand" HorizontalOptions="StartAndExpand" /> <!-- Delete "Icon" --> <Label Text="Clickable Label" VerticalOptions="CenterAndExpand" HorizontalOptions="EndAndExpand"> <Label.GestureRecognizers> <TapGestureRecognizer Command="{Binding Path=BindingContext.OnClickableLabel, Source={x:Reference Page}}" CommandParameter="{Binding .}" /> </Label.GestureRecognizers> </Label> </StackLayout> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </ContentPage.Content> </ContentPage> 

After that, I got the OnClickableLabel command launched inside my ViewModel page, as expected :).

If someone knows the β€œbest” solution (better in terms of XAML code), I would like to see it;).

Thanks everyone!

+5
source

All Articles