Question XAML - ItemTapped no working

Riffy100

Member
Joined
Jul 24, 2021
Messages
11
Programming Experience
Beginner
Hi

I am unable to get ItemTapped working. I am using VS 2019/XAML/C#.

When I click on a selected item, nothing happens.

I have following xaml code in my ItemsPage.xaml:


C#:
     <StackLayout.GestureRecognizers>
                                <TapGestureRecognizer
                                    NumberOfTapsRequired="1"
                                    Command="{Binding Source={RelativeSource AncestorType={x:Type local:ItemsViewModel}}, Path=ItemTapped}"       
                                    CommandParameter="{Binding .}">
                                </TapGestureRecognizer>
                            </StackLayout.GestureRecognizers>
                        </StackLayout>

The ItemsPage. c has following code:

C#:
    namespace IRKL.Views
    {
        public partial class ItemsPage : ContentPage
        {
            private readonly ItemsViewModel _viewModel;
            readonly ObservableCollection<Item> items = new ObservableCollection<Item>();
            public ObservableCollection<Item> Item { get { return items; } }
    
            public ItemsPage()
            {
                InitializeComponent();
    
                BindingContext = _viewModel = new ItemsViewModel();
    
    
                items = new ObservableCollection<Item>()
                        {
                         new Item { Id = Guid.NewGuid().ToString(), Text = "TEST", Description = "TEST" },
                     };
                BindingContext = this;
    
            }
             protected override void OnAppearing()
            {
    
                base.OnAppearing();
                _viewModel.OnAppearing();
    
                    //build data for ItemsPage
                
            }
      
        }
    
    }

The ItemsViewModel.cs codes is as follows:


C#:
    namespace IRKL.ViewModels
    {
        public class ItemsViewModel : BaseViewModel
        {
            private Item _selectedItem;
    
            public ObservableCollection<Item> Items { get; }
            public Command LoadItemsCommand { get; }
            public Command AddItemCommand { get; }
            public Command<Item> ItemTapped { get; }
    
            public ItemsViewModel()
            {
                //Title = "Browse";
                Items = new ObservableCollection<Item>();
          
                //LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand());
    
                ItemTapped = new Command<Item>(OnItemSelected);
    
                AddItemCommand = new Command(OnAddItem);
            }
    
            async Task ExecuteLoadItemsCommand()
            {
                IsBusy = true;
    
                try
                {
                    Items.Clear();
                    var items = await DataStore.GetItemsAsync(true);
                    foreach (var item in items)
                    {
                        Items.Add(item);
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex);
                }
                finally
                {
                    IsBusy = false;
                }
    
            }
            public void OnAppearing()
            {
                IsBusy = true;
                SelectedItem = null;
            }
    
            public Item SelectedItem
            {
                get => _selectedItem;
                set
                {
                    SetProperty(ref _selectedItem, value);
                    OnItemSelected(value);
                }
            }
    
            private async void OnAddItem(object obj)
            {
                await Shell.Current.GoToAsync(nameof(NewItemPage));
            }
    
            async void OnItemSelected(Item item)
            {
                if (item == null)
                    return;
                
                await Shell.Current.GoToAsync($"{nameof(ItemDetailPage)}?{nameof(ItemDetailViewModel.ItemId)}={item.Id}");
             }
    
            protected bool SetProperty<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
            {
                if (!Equals(field, newValue))
                {
                    field = newValue;
                    return true;
                }
    
                return false;
            }
    
            private System.Collections.IEnumerable item1;
    
            public System.Collections.IEnumerable Item { get => item1; set => SetProperty(ref item1, value); }
          
        }
    }

When a displayed Item is clicked, nothing happens. I am expecting the following method to be triggered :


C#:
            async void OnItemSelected(Item item)
            {
                if (item == null)
                    return;
                
                await Shell.Current.GoToAsync($"{nameof(ItemDetailPage)}?{nameof(ItemDetailViewModel.ItemId)}={item.Id}");
             }

Any suggestions to resolve problem would be greatly appreciated.

Thanks
 
Solution
In post #5, I was talking about your expectation that the SelectedItem property would be change and how you are calling OnItemSelected() as part of that expectation. But if you don't have a binding for SelectedItem, how would it even be updated by the UI?

Anyway, that's an aside. It you also have a binding for the TapGestureRecognizer.Command which should also call your OnItemSelected(). Assuming that the binding expression you have there is correct, then things should work. But if you say that the breakpoint isn't being called then either the binding is incorrect, or there is a bug in Xamarin that preventing calling the bound command object.

I would suggest temporarily commenting out using the...
I have uncluded the full XAML page for ItemPage.xaml

C#:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="IRKL.Views.ItemsPage"
             Title="{Binding Title}" BackgroundColor="AliceBlue"
             xmlns:local="clr-namespace:IRKL.ViewModels" 
             xmlns:model="clr-namespace:IRKL.Models"
             x:Name="BrowseItemsPage">
    

    <ContentPage.ToolbarItems>
        <ToolbarItem Text="Audio" Clicked="PlayAudioCommand" />
    </ContentPage.ToolbarItems>
    <CollectionView BackgroundColor="{StaticResource  PageBckColour}"
                        ItemsSource="{Binding Item}"
                        SelectionMode="Single"
                    SelectionChanged="OnCollectionViewSelectionChanged">
        <CollectionView.ItemTemplate>
                <DataTemplate>
                    <StackLayout Padding="7" x:DataType="model:Item" Spacing="3">
                    <Label Text="{Binding Text}"
                            LineBreakMode="NoWrap"
                            Style="{DynamicResource ListItemTextStyle}"
                            TextColor="{StaticResource TxtColour}"
                            FontAttributes="Bold"
                            FontSize="15" ></Label>
                    <ScrollView>
                        <StackLayout>
                            <Label Text="{Binding Description}"
                            Style="{DynamicResource ListItemDetailTextStyle}"
                            TextColor="{StaticResource DescTxtColour}"
                            FontSize="13"
                            FontAttributes="Bold" />
                        </StackLayout>
                    </ScrollView>
                    <StackLayout.GestureRecognizers>
                            <TapGestureRecognizer
                                NumberOfTapsRequired="1"
                                Command="{Binding Source={RelativeSource AncestorType={x:Type local:ItemsViewModel}}, Path=ItemTapped}"       
                                CommandParameter="{Binding .}">
                            </TapGestureRecognizer>
                        </StackLayout.GestureRecognizers>
                    </StackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

</ContentPage>
 
Does the issue reproduce in the emulator?

Can you set a breakpoint at the beginning of the method? Does the breakpoint get hit?
 
Does the issue reproduce in the emulator?

Can you set a breakpoint at the beginning of the method? Does the breakpoint get hit?
Hi

I have set the break point as follows:

1641306064913.png


and at

1641306138484.png


They do no get hit. Clicking on any item on the list does not result on any code being run, as far as I can tell.

Thank you for your help.
 
The breakpoint shouldn't be on the get, but rather the set for the first chunk of code in post #4

In your XAML in post #2, I'm not seeing any binding for SelectedItem, so I'm unsure how you are expecting your set in your model to be called.

Anyway, it looks like your OnAppearing() may also not be called. I would have expected the line SelectedItem = null; on line 50 of your ItemsViewModel.cs in post #1 to call OnItemSelected() passing in a null. But if you say that the breakpoint on line 77 of the second chunk of code in post #4 is not being hit then very likely OnAppearing() is not being called.
 
Hi

I was in the process of creating another page when I got your reply. But the Templates for new item in VS 2019 had disappeared, I did a rebuild with VS Studio Installer and got the templates back.

I then tried to rebuild my solution, to investigate the Onselection issue and ended up getting the following errors from the rebuild

CS0006 Metadata file D::\..........................\repos...\bin\Debug\NETSTANDARD2.0\Ref\IRKL.dll not found
XCF0002 EventHandler "OnCollectionViewSelectionChanged" with correct signature found in type "IRKL.Views.ItemsPage File: ItemsPage.xaml Line 17

I don't believe I have changed anything to create the errors, or whether the VS 2019 Installer rebuild cause the errors.

Being a beginner, I haven't had much success with resolving these errors. I know that this is not connected to my initial post, but any help would be greatly appreciated. Why does VS 2019 sometimes throw up erroneous errors, some of which disappear once you close and restart the project. Classic eg is error with InitialiseComponent()


Thanks
 
Sorry, I don't use VS with Xamarin enough to help. Hopefully someone can jump in and help.
 
Sorry, I don't use VS with Xamarin enough to help. Hopefully someone can jump in and help.
As per online suggestions, I have tried unloading,loading and rebuliding solutions/projects to reslove the dll error - withuot any success. Also deleting bin/obj folders and rebuilding solution did not work.
 
I managed to get rid of the CS0006 Metadata file D::\..........................\repos...\bin\Debug\NETSTANDARD2.0\Ref\IRKL.dll not found error, by Changing multiple times the build configuration.

@Skydiver - With reference to post 5, the Item that is Tapped is the Text field :

C#:
<Label Text="{Binding Text}"
                            LineBreakMode="NoWrap"
                            Style="{DynamicResource ListItemTextStyle}"
                            TextColor="{StaticResource TxtColour}"
                            FontAttributes="Bold"
                            FontSize="15" ></Label>

Please accept my apologies, if that is not what you mean. I am really keen to resolve this issue and it is blocking progress on my project, so any further suggestions to resolving the Tapping/Selection issue.

Thanks
 
In post #5, I was talking about your expectation that the SelectedItem property would be change and how you are calling OnItemSelected() as part of that expectation. But if you don't have a binding for SelectedItem, how would it even be updated by the UI?

Anyway, that's an aside. It you also have a binding for the TapGestureRecognizer.Command which should also call your OnItemSelected(). Assuming that the binding expression you have there is correct, then things should work. But if you say that the breakpoint isn't being called then either the binding is incorrect, or there is a bug in Xamarin that preventing calling the bound command object.

I would suggest temporarily commenting out using the Command and CommandParameter and try using the TappedCallback and TappedCallbackParameter without using MVVM to see if that works. If it those, then go back to using MVVM but use the simplest possible binding first like in the Xamarin documentation, and see if that works. If it does, then work your way back to your original code with that complex binding.

 
Solution
Back
Top Bottom