Do WPF have Touch-and-Hold gesture?

后端 未结 2 1328
抹茶落季
抹茶落季 2021-01-15 04:55

Do WPF have Touch-and-Hold gesture? I cannot find event for that, so I tried to implement one for myself. I know that there is Stylus class but in WPF it does n

相关标签:
2条回答
  • 2021-01-15 05:24

    I've previously achieved this by create a custom control that extends button to delay the trigger of a button command after a delay on press-and-hold.

    public class DelayedActionCommandButton : Button
    

    First dependency properties:

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

    These give us a control on how the delay should be and an output of how long is left.

    Next I create an animation, to control the elapsed amount which when complete fires the command. There is also a cancel delay method:

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

    Finally, we wire up the event handlers:

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

    When used in XAML, you can optionally create a template that can animate based on the value of DelayElapsed to provide a countdown, or visual cue such as an expanding border, whatever takes your fancy.

    0 讨论(0)
  • 2021-01-15 05:25

    It is possible to do that in an awaitable fashion. Create a timer with specific interval. Start it when user tapped and return the method when timer elapsed. If user release the hand, return the method with false flag.

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

    For more information, read this post.

    0 讨论(0)
提交回复
热议问题