WPF 是不是有触摸并按住手势?

Posted

技术标签:

【中文标题】WPF 是不是有触摸并按住手势?【英文标题】:Do WPF have Touch-and-Hold gesture?WPF 是否有触摸并按住手势? 【发布时间】:2014-08-05 08:49:22 【问题描述】:

WPF 是否有长按手势?我找不到那个事件,所以我尝试为自己实现一个。我知道有 Stylus 类,但在 WPF 中它对我没有帮助。如果没有,那就是我的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
namespace WebControlTouch

    /// <summary>
    /// Due to lack of Touch-and-Hold gesture, here is implementation of it. Stupid M$.
    /// </summary>
    public static class Touch_and_Hold
    
        #region Constructor + methods
        /// <summary>
        /// Static constructor which creates timer object with 1000ms interval, also sets parameters of Timer.
        /// </summary>
        static Touch_and_Hold()
        
            gestureTimer = new Timer(1000);
            gestureTimer.AutoReset = false;
            gestureTimer.Elapsed += gestureTimer_Elapsed;
        
        /// <summary>
        /// On elasped (time ofc)
        /// </summary>
        /// <seealso cref="gestureTimer"/>        
        static void gestureTimer_Elapsed(object sender, ElapsedEventArgs e)
        
            occured = true;
        
        /// <summary>
        /// Call it on OnTouchDown event.
        /// It will start timer and will count time of touch
        /// </summary>
        /// <returns>Returns that gesture occured</returns>
        public static void onTouch()
        
            gestureTimer.Start();
        

        /// <summary>
        /// Call it on touch up mainwindow event (or somewhere else)
        /// It stops gesture timer
        /// </summary>
        public static void onTouchUp()
        
        occured = false;
        
        #endregion 
        #region Members + properties
        /// <summary>
        /// Timer for measuring touchTime
        /// </summary>
        private static Timer gestureTimer;
        /// <summary>
        /// Do tap-and-hold occured
        /// </summary>
        private static bool occured = false;
        /// <summary>
        /// Property for getting occured flag
        /// </summary>
        public static bool occuredGesture
        
            get  return occured; 
        
        #endregion
    


如果是,请告诉我活动名称。如果不是 - 尝试引导我解决问题。 任何帮助将不胜感激。

【问题讨论】:

我最近做了一些类似的事情来创建一个自定义按钮,一旦按下设定的时间就会触发它的命令。我找不到事件,但我想将剩余时间作为控件上的属性公开,以便它可以绑定到 - 出于视觉糖果的目的。如果这听起来像是一个修复,我可以发布代码。 那太好了:) 【参考方案1】:

有可能以等待的方式做到这一点。创建具有特定间隔的计时器。当用户点击时启动它,并在计时器经过时返回该方法。如果用户松开手,则返回带有 false 标志的方法。

public static Task<bool> TouchHold(this FrameworkElement element, TimeSpan duration)

    DispatcherTimer timer = new DispatcherTimer();
    TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
    timer.Interval = duration;

    MouseButtonEventHandler touchUpHandler = delegate
    
        timer.Stop();
        if (task.Task.Status == TaskStatus.Running)
        
            task.SetResult(false);
        
    ;

    element.PreviewMouseUp += touchUpHandler;

    timer.Tick += delegate
    
        element.PreviewMouseUp -= touchUpHandler;
        timer.Stop();
        task.SetResult(true);
    ;

    timer.Start();
    return task.Task;

欲了解更多信息,请阅读此post。

【讨论】:

【参考方案2】:

我之前通过创建一个自定义控件来实现这一点,该控件扩展按钮以在按住延迟后延迟按钮命令的触发。

public class DelayedActionCommandButton : Button

第一个依赖属性:

public static readonly DependencyProperty DelayElapsedProperty =
        DependencyProperty.Register("DelayElapsed", typeof(double), typeof(DelayedActionCommandButton), new PropertyMetadata(0d));

public static readonly DependencyProperty DelayMillisecondsProperty =
        DependencyProperty.Register("DelayMilliseconds", typeof(int), typeof(DelayedActionCommandButton), new PropertyMetadata(1000));

public double DelayElapsed
    
        get  return (double)this.GetValue(DelayElapsedProperty); 
        set  this.SetValue(DelayElapsedProperty, value); 
    

    public int DelayMilliseconds
    
        get  return (int)this.GetValue(DelayMillisecondsProperty); 
        set  this.SetValue(DelayMillisecondsProperty, value); 
    

这些让我们可以控制延迟应该如何以及剩余多长时间的输出。

接下来我创建一个动画,以控制完成后触发命令的经过量。还有一种取消延迟的方法:

    private void BeginDelay()
    
        this._animation = new DoubleAnimationUsingKeyFrames()  FillBehavior = FillBehavior.Stop ;
        this._animation.KeyFrames.Add(new EasingDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0)), new CubicEase()  EasingMode = EasingMode.EaseIn ));
        this._animation.KeyFrames.Add(new EasingDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(this.DelayMilliseconds)), new CubicEase()  EasingMode = EasingMode.EaseIn ));
        this._animation.Completed += (o, e) =>
        
            this.DelayElapsed = 0d;
            this.Command.Execute(this.CommandParameter);    // Replace with whatever action you want to perform
        ;

        this.BeginAnimation(DelayElapsedProperty, this._animation);
    

    private void CancelDelay()
    
        // Cancel animation
        this.BeginAnimation(DelayElapsedProperty, null);
    

最后,我们连接事件处理程序:

private void DelayedActionCommandButton_TouchDown(object sender, System.Windows.Input.TouchEventArgs e)
    
        this.BeginDelay();
    

    private void DelayedActionCommandButton_TouchUp(object sender, System.Windows.Input.TouchEventArgs e)
    
        this.CancelDelay();
    

在 XAML 中使用时,您可以选择创建一个模板,该模板可以根据 DelayElapsed 的值进行动画处理,以提供倒计时或视觉提示(如扩展边框),随心所欲。

【讨论】:

感谢您的代码。我会根据我的目的重复使用它。你帮了我很多:) 不用担心 - 很高兴我能提供帮助。

以上是关于WPF 是不是有触摸并按住手势?的主要内容,如果未能解决你的问题,请参考以下文章

WPF 多点触摸开发[2]:WPF触摸的几个手势的执行顺序

为啥 UITableViewCell 上的 UIButton 仅在触摸手势持续很短时间时才会变暗

Xamarin:获取手势触摸是不是在某个元素内

Mapbox长按手势后在地图上查找注释

Swift Game - 点击并点击 + 按住手势?

iOS 手势大全