0
votes

I have this problem with Xamarin Forms (Tested on Android and iOS).

I have a simple page

using System;

using Xamarin.Forms;

namespace BugTGR
{
    public class PageMain : ContentPage
    {
        public PageMain()
        {
            PageMainViewModel vm = new PageMainViewModel();
            this.BindingContext = vm;

            Label label1 = new Label{ Text = "Press with ICommand"};

            TapGestureRecognizer tgr = new TapGestureRecognizer();
            tgr.BindingContext = vm;
            tgr.SetBinding(TapGestureRecognizer.CommandProperty, "Tapped");
            label1.GestureRecognizers.Add(tgr);

            Label label2 = new Label { Text = "Press with Tapped"};
            TapGestureRecognizer tgr1 = new TapGestureRecognizer();
            tgr1.Tapped += async (object sender, EventArgs e) => {
                await DisplayAlert("Attention", "PRESSED WITH TAPPED", "Ok");
            };
            label2.GestureRecognizers.Add(tgr1);

            Content = new StackLayout
            {

                Children = {label1, label2}
            };
        }
    }
}

In this code, I use this ViewModel (very simple, only a command)

using System;
using System.Windows.Input;
using Xamarin.Forms;
using PropertyChanged;
namespace BugTGR
{
    [ImplementPropertyChanged]
    public class PageMainViewModel 
    {
        public PageMainViewModel()
        {

            this.Tapped = new Command(async() =>
            {
                await Application.Current.MainPage.DisplayAlert("Attention", "Pressed", "Ok");
            });

        }

        public ICommand Tapped { protected get; set;}
    }
}

Then, how you can see, I try to Bind the Command to a TapGestureRecognizer, then add the TGR to a label, but if I click the label, the command is not called.

In the second label (label2) I add another TapGestureRecognizer without bind the command, using Tapped event. This works!

There is someone that can let me know what am I doing wrong?

Thanks! Alessandro

1
I don't see the issue yet. What is not working and which platform are you testing this on? Also, make sure that your Xamarin.Forms versions are up-to-date. - therealjohn
@therealjohn I have tested on Android and iOS. I am using last XF version. I do some other research - Alessandro Caliaro
I just figured it out, but it looks like Yuri posted before I could. :) - therealjohn
@therealjohn Hey, I am ahead of Microsoft engineer, LOL. Thanks for the vote - Yuri S

1 Answers

4
votes

Here is working solution. The problem is how you create Tapped command. Below is 2 ways of doing this. Command or event handler calling VM. If you are doing this in code and not in xaml I would use vm.TappedHandler method

namespace ButtonRendererDemo
{
    public class LabelTapPage : ContentPage
    {
        public LabelTapPage()
        {
            PageMainViewModel vm = new PageMainViewModel();
            this.BindingContext = vm;

            Label label1 = new Label { Text = "Press with ICommand" };
            TapGestureRecognizer tgr = new TapGestureRecognizer();
            label1.GestureRecognizers.Add(tgr);
            tgr.SetBinding(TapGestureRecognizer.CommandProperty, "Tapped");

            Label label2 = new Label { Text = "Press with Tapped Event" };
            TapGestureRecognizer tgr1 = new TapGestureRecognizer();
            tgr1.Tapped += async (object sender, EventArgs e) => {
                await DisplayAlert("Attention", "Tapped Event: Pressed", "Ok");
            };
            label2.GestureRecognizers.Add(tgr1);

            Label label3 = new Label { Text = "Press with TappedHandler" };
            var tapGestureRecognizer = new TapGestureRecognizer();
            tapGestureRecognizer.Tapped += async (s, e) => {
                await vm.TappedHandler();
            };
            label3.GestureRecognizers.Add(tapGestureRecognizer);


            Content = new StackLayout
            {

                Children = { label1, label2, label3 }
            };
        }
    }


    public class PageMainViewModel : INotifyPropertyChanged
    {
        ICommand tapCommand;

        public PageMainViewModel()
        {
            tapCommand = new Command(OnTapped);
        }

        public async Task TappedHandler()
        {
            await Application.Current.MainPage.DisplayAlert("Attention", "TappedHandler: Pressed", "Ok");
        }


        public ICommand Tapped
        {
            get { return tapCommand; }
        }

        async void OnTapped(object s)
        {
            await Application.Current.MainPage.DisplayAlert("Attention", "Tapped Command: Pressed", "Ok");
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }

}

Also you don't need to set tgr.BindingContext = vm; It is inherited by your page

After I published it I found that there is much easier solution:

Remove "protected" in

public ICommand Tapped { get; set; }

so page can access it. That's it :-)

May be you meant make "set" protected not get?