在 ListView 中点击手势手势识别器不起作用
Posted
技术标签:
【中文标题】在 ListView 中点击手势手势识别器不起作用【英文标题】:Tap Gesture Gesture Recognizer in ListView not working 【发布时间】:2016-11-17 16:46:09 【问题描述】:我的 ViewModel 中有这个:
public class MyClass: INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
int taps = 0;
ICommand tapCommand;
public MyClass()
tapCommand = new Command(OnTapped);
public ICommand TapCommand
get return tapCommand;
void OnTapped(object s)
taps++;
Debug.WriteLine("parameter: " + s);
这在 xaml 中:
<Image Source="delete.jpg" HeightRequest="20" WidthRequest="20">
<Image.GestureRecognizers>
<TapGestureRecognizer
Command="Binding TapCommand"
CommandParameter="Image1" />
</Image.GestureRecognizers>
</Image>
但是当单击图像时,输出日志中不会出现任何内容。我错过了什么?
注意 1:我已按照指南 here
注意 2:我正在 android 设备上调试
更新 1:完整的 xaml here
【问题讨论】:
列表视图在哪里?图像是 DataTemplate 的一部分吗?你能提供更多的xaml吗? 我无法重现此内容。我得到 [0:] 参数:Image1 问题已更新为完整的 xaml pastebin 链接@YuriS 经过一番尝试后,我注意到列表视图外部的图像点击有效,但列表视图内部却没有。 @YuriS 【参考方案1】:您没有提供任何代码,所以我必须创建自己的代码(见下文)。 如果注释掉 ListView IsEnabled="False"
,您还可以为我节省 15 分钟当您设置Command="Binding TapCommand
时,TapCommand 对应于列表项的 TapCommand,而不是模型本身。所以,你有两个选择
-
您可以在 MyItem 中实现点击(我认为您不希望这样做,所以它的部分代码在下面的 MyItem 类中注释)
在图像本身上定义上下文绑定。
因为我们的视图模型可以创建几次——我们不希望这样,所以最好的解决方案是定义视图模型的静态资源并在页面上的任何地方使用它。
解决方案如下(您只需修改一些命名空间并将 delte.png 更改为您的 delete.jpg):
页面 xml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ButtonRendererDemo;assembly=ButtonRendererDemo"
x:Class="ButtonRendererDemo.ImageTapComplexPage"
BindingContext="StaticResource viewModel">
<ContentPage.Resources>
<ResourceDictionary>
<local:TapComplexViewModel x:Key="viewModel"/>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<Label Text="text2" VerticalOptions="Center" HorizontalOptions="Center" />
<StackLayout Padding="0,20,0,20">
<Button Text="text" Clicked="onclick" BackgroundColor="#009688"></Button>
</StackLayout>
<Label Text="List Type" VerticalOptions="Center" HorizontalOptions="Center" />
<ListView x:Name="lstItems" RowHeight="60" ItemsSource="Binding Items" > <!--IsEnabled="False"-->
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" HorizontalOptions="Fill" Padding="0,2,0,2">
<StackLayout Padding="5,5,5,5">
<Image Source="Binding source" HorizontalOptions="End" HeightRequest="40" WidthRequest="40" />
</StackLayout>
<StackLayout Orientation="Vertical" Spacing="1">
<Label Text = "Binding name" HeightRequest="20" FontAttributes="Bold"/>
<Label Text = "Binding data, StringFormat='0:F0'" />
</StackLayout>
<StackLayout HorizontalOptions="EndAndExpand" Padding="0,0,15,0" Orientation="Horizontal">
<Image Source="delete.png" HeightRequest="20" WidthRequest="20">
<Image.GestureRecognizers>
<!--<TapGestureRecognizer
Command="Binding TapCommand"
CommandParameter="Image1" />-->
<TapGestureRecognizer Command="Binding Source=StaticResource viewModel, Path=TapCommand" CommandParameter="Binding name" />
</Image.GestureRecognizers>
</Image>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
后面的代码
namespace ButtonRendererDemo
public partial class ImageTapComplexPage : ContentPage
public ImageTapComplexPage()
InitializeComponent();
void onclick(object sender, EventArgs args)
public class TapComplexViewModel : INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
int taps = 0;
ICommand tapCommand;
public ObservableCollection<MyItem> Items get; private set;
public TapComplexViewModel()
Items = new ObservableCollection<MyItem>()
new MyItem name="First", source="Icon.png", data=0.5f ,
new MyItem name="Second", source="Icon.png", data=0.6f ,
new MyItem name="Third", source="Icon.png", data=0.7f
;
tapCommand = new Command(OnTapped);
public ICommand TapCommand
get return tapCommand;
void OnTapped(object s)
taps++;
Debug.WriteLine("parameter: " + s);
public class MyItem
public string name get; set;
public string source get; set;
public float data get; set;
//public ICommand TapCommand
//
// get return new Command(() => );
//
【讨论】:
如果您对如何将点击从您的模型传递到页面有疑问,您可以创建一个单独的问题并告诉我。我也有这个解决方案。【参考方案2】:在 xaml 文件的后端,确保将 BindingContext 设置为视图模型:像这样:
xaml.cs
public partial class TapInsideFrameXaml : ContentPage
public TapInsideFrameXaml ()
InitializeComponent ();
// The TapViewModel contains the TapCommand which is wired up in Xaml
BindingContext = new TapViewModel ();
同时检查:
在菜单 > 工具 > 选项 > 调试 > 常规:
确保未选中“将所有输出窗口文本重定向到即时窗口”关于项目属性 > 构建:
配置:调试 选中“定义调试常量” “定义跟踪常数”被选中在输出窗口中:
显示来自:调试的输出 在输出窗口中右键单击并确保选中“程序输出”还要确保您使用 F5 而不是 Ctrl f5 进行调试
【讨论】:
您尝试添加一个断点并查看该命令是否被调用? 您希望输出日志在哪里? 图像点击 -> 输出:参数:Image1 好的,这是我最后的选择,试试 Console.WriteLine()【参考方案3】:您声明了PropertyChangedEvent
事件,但您从未实际使用它。试试这个:
public class MyClass: INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
int taps = 0;
ICommand tapCommand;
public MyClass()
tapCommand = new Command(OnTapped);
public ICommand TapCommand
get return tapCommand;
void OnTapped(object s)
taps++;
Debug.WriteLine("parameter: " + s);
OnPropertyChanged();
protected virtual void OnPropertyChanged ([CallerMemberName] string propertyName = null)
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler (this, new PropertyChangedEventArgs (propertyName));
【讨论】:
以上是关于在 ListView 中点击手势手势识别器不起作用的主要内容,如果未能解决你的问题,请参考以下文章