mvvm - Xamarin Forms 和 TabGestureRecognizer 不会使用 Command 触发

标签 mvvm xamarin xamarin.forms

我对 Xamarin Forms 有这个问题(在 Android 和 iOS 上测试)。

我有一个简单的页面

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}
            };
        }
    }
}

在这段代码中,我使用了这个ViewModel(很简单,只有一个命令)
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;}
    }
}

然后,您怎么看,我尝试将命令绑定(bind)到TapGestureRecognizer,然后将TGR添加到标签,但是如果单击标签,则不会调用该命令。

在第二个标签 (label2) 中,我添加了另一个 TapGestureRecognizer 而不绑定(bind)命令,使用 Tapped 事件。这行得通!

有人可以让我知道我做错了什么?

谢谢!
亚历山德罗

最佳答案

这是工作解决方案。问题是如何创建 Tapped 命令。
以下是执行此操作的 2 种方法。调用 VM 的命令或事件处理程序。如果您在代码中而不是在 xaml 中执行此操作,我将使用 vm.TappedHandler 方法

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;
    }

}

你也不需要设置 tgr.BindingContext = vm;它由您的页面继承

在我发布它之后,我发现有更简单的解决方案:

删除“ protected ”
public ICommand Tapped { get; set; }

所以页面可以访问它。就是这样 :-)

可能你的意思是让“设置” protected 没有得到?

关于mvvm - Xamarin Forms 和 TabGestureRecognizer 不会使用 Command 触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41109340/

相关文章:

.net - 无法在 NavigationView MenuItemTemplate 中绑定(bind) Icon 属性

wpf - 在 View 模型中包含 WPF 细节的优缺点

android - 无法在 xamarin 中的 android Activity 之间传递数据

html - Xamarin 在标签中形成 HTML

xaml - 如何检查 xamarin 表单数据触发器中的对象空值?

swift - Swift 4 中使用 MVVM 绑定(bind)不会触发 ViewController 中的事件

c# - 从 AvalonDock 2.0 中的集合绑定(bind) LayoutDocument 的标题

c# - 如何将 itemsource(字符串数组)的值绑定(bind)到 ListView 中的标签

c# - 如何在 Xamarian iOS 应用程序中单击按钮 X 秒后触发事件?

android - Xamarin 完全形成 Java.Lang.IllegalArgumentException : DrawerLayout must be measured with MeasureSpec.