TapGestureRecognizer 在 ListView 中不起作用 [英] TapGestureRecognizer not working inside ListView

查看:31
本文介绍了TapGestureRecognizer 在 ListView 中不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理一个 Xamarin.Forms 页面,该页面使用 MVVM 模式显示项目列表.

I am working on a Xamarin.Forms page displaying a list of items using MVVM pattern.

我无法获取正在工作的列表项的 TapGestureRecognizer 对象的 Command 属性.无论我尝试什么,它都不会触发.此命令属性应为所有列表视图元素引用 VM 上的单个 ICommand 属性.CommandParameter 属性应根据元素的 ID 在元素之间进行选择.

I can not get the Command property of the TapGestureRecognizer object of the list items working. It does not even fire, no matter what I try. This command property should reference a single ICommand property on the VM for all the listview elements. The CommandParameter property should select between the elements based on their Id.

Tapped 事件似乎有效.我不确定我的 Command 属性到 VM 的数据绑定是否有问题,或者 Xamarin.Forms 在这里有错误.

The Tapped event seems to be working. I am not sure whether my databinding of the Command property to the VM is faulty or Xamarin.Forms has a bug here.

我尝试了不同的设置,将 TapGestureRecognizer 的 Command 属性的数据绑定到我的 ViewModel,并且我还在嵌套的 View 元素上使用了 InputTransparent 属性.这里没有变化:命令不会触发

I have tried different settings for the data binding of TapGestureRecognizer's Command property to my ViewModel and I have also played with the InputTransparent properties on the nested View-elements. No change here: Command does not fire

查看 XAML 标头:

View XAML header:

<ContentPage ...
             x:Class="Ch9.MainPage2"
             x:Name="page"
             >

View 有一个 ViewModel 属性,它是视图模型:

View has a ViewModel property which is the viewmodel:

public partial class MainPage2 : ContentPage
{
    public MainPage2ViewModel ViewModel
    {
       get => BindingContext as MainPage2ViewModel;
       set => BindingContext = value;
    }

        public MainPage2()
        {
            InitializeComponent();
            ViewModel = new MainPage2ViewModel(
            ...injecting components...
             );
        }
}

视图模型有一个 ItemTappedCommand 属性:

the viewmodel has an ItemTappedCommand property:

public ICommand ItemTappedCommand { get; private set; }
...
ItemTappedCommand = new Command<int>(async id => await OnItemTappedCommand(id));

在页面内,我有一个 stacklayout 作为 content-root,在 stacklayout 内有一个 listview.为了保持代码小,我省略了我能做的,我认为不相关的

Inside the page I have a stacklayout as content-root and inside the stacklayout there is a listview. To keep the code small, I have omitted what I could, what I think is not relevant

<ListView
    ItemsSource="{Binding SearchResults}">
    <ListView.ItemTemplate>
    <DataTemplate>                        
        <ViewCell>
            <StackLayout>
                <StackLayout.GestureRecognizers>
                      <TapGestureRecognizer 
                            BindingContext="{x:Reference page}"                                        
                            Command="{Binding Path=ViewModel.ItemTappedCommand}" CommandParameter="{Binding Id}"  NumberOfTapsRequired="1"/>
                </StackLayout.GestureRecognizers>

                                <Image InputTransparent="True">
                                    <Image.Source>
                                        <UriImageSource Uri="{Binding ImgSmSrc}"
                                                    CacheValidity="0"
                                                    CachingEnabled="False"                                                    
                                                    />
                                    </Image.Source>
                                </Image>
                               <StackLayout InputTransparent="True">
                              some content...
                              </StackLayout>

                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>

推荐答案

您已将 TapGestureRecognizerBindingContext 更改为您当前的内容页面,但它无法注意到自定义定义的属性ViewModel,您只能使用ContentPage 的属性.

You've changed your TapGestureRecognizer's BindingContext to your current content page but it could not notice the customized defined property ViewModel, you can only consume the ContentPage's property.

所以{Binding Path=ViewModel.ItemTappedCommand}这个绑定会失败.

我建议您调整绑定,例如:

I recommend you to adjust your binding like:

<ListView x:Name="listView" ItemsSource="{Binding SearchResults}" HasUnevenRows="True">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout>
                    <StackLayout.GestureRecognizers>
                        <TapGestureRecognizer Command="{Binding Path= BindingContext.ItemTappedCommand, Source={x:Reference listView}}" 
                                            CommandParameter="{Binding Id}"  
                                            NumberOfTapsRequired="1"/>
                    </StackLayout.GestureRecognizers>
                    <!--onther stuff-->
                    <!--...-->

                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

listView 的绑定上下文是您使用隐藏代码设置的视图模型.最后,您可以在那里使用 ItemTappedCommand.

The listView's binding context is your view model which has been set using code behind. At last you could consume the ItemTappedCommand there.

此外,由于您想访问 Id,我只更改了 CommandSource 而不是整个手势的绑定上下文.或者你不会检索它,因为它属于 SearchResults 的元素而不是视图模型本身.

Moreover, as you want to access the Id, I only changed the Command's Source instead of the whole gesture's binding context. Or you won't retrieve that because it belongs to the element of SearchResults not view model itself.

这篇关于TapGestureRecognizer 在 ListView 中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆