【问题标题】:Tap Gesture Gesture Recognizer in ListView not working在 ListView 中点击手势手势识别器不起作用
【发布时间】: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

标签: android objective-c listview xamarin uitapgesturerecognizer


【解决方案1】:

您没有提供任何代码,所以我必须创建自己的代码(见下文)。 如果注释掉 ListView IsEnabled="False"

,您还可以为我节省 15 分钟

当您设置Command="{Binding TapCommand} 时,TapCommand 对应于列表项的 TapCommand,而不是模型本身。所以,你有两个选择

  1. 您可以在 MyItem 中实现点击(我认为您不希望这样做,所以它的部分代码在下面的 MyItem 类中注释)
  2. 在图像本身上定义上下文绑定。 因为我们的视图模型可以创建几次——我们不希望这样,所以最好的解决方案是定义视图模型的静态资源并在页面上的任何地方使用它。 解决方案如下(您只需修改一些命名空间并将 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));
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多