如何在WPF应用程序中检测触摸按住手势?

时间:2013-01-15 12:22:40

标签: wpf touch gesture

可以使用MouseRightButtonDown事件检测触摸按住并保持手势。不幸的是,直到我从屏幕上松开手指才开始发射。这是迟到的!

有没有人有想法?提前谢谢。

5 个答案:

答案 0 :(得分:5)

有可能以一种等待的方式做到这一点。创建具有特定间隔的计时器。用户点击时启动它,并在计时器结束后返回方法。如果用户释放了手,则返回带有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

答案 1 :(得分:2)

很棒的代码。我只添加了一个完整性的示例用法:

private async void btn_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
  if (await TouchHold(btn, TimeSpan.FromSeconds(2)))
  {
    // todo: long press code goes here
  }
}

来自XAML:

<Button Name="btn" PreviewMouseDown="btn_PreviewMouseDown">Press long</Button>

答案 2 :(得分:1)

使用Blake.NUI toolkit

提供的暂停手势

答案 3 :(得分:0)

无论是按钮,标签还是图像,我们都可以使用MouseDownMouseUp来启动延迟和停止延迟。

对于MouseDown

    // Declaration of timer and timercount
     int timerCount = 0;
     DispatcherTimer dt = new DispatcherTimer();

     public myConstructor()
            {
                dt.Interval = new TimeSpan(0, 0, 1);
            }

    // Mouse Down Event
     private void EnterHoldState(object sender, TouchEventArgs e)
            {
                timerStarted();
            }

    //Mouse Up event
        private void ExitHoldState(object sender, RoutedEventArgs e)
                {
                    timerStopped();
                }

// Stops the timer and resets the timer count to 0
        private void timerStopped()
        {
            dt.Stop();
            timerCount = 0;
        }

// Starts the timer and sets delayCounter function for counting the delay seconds and acts on it
        private void timerStarted()
        {
            dt.Tick += delayCounter;
            dt.Start();
            
        }

//Once delay timer reaches 2 seconds, the button navigates to nextpage.
        private void delayCounter(object sender, EventArgs e)
        {
            timerCount++;
            if (timerCount == 2)
            {
                this.NavigationService.Navigate(new nextPage());
            }
        }

答案 4 :(得分:0)

我最近不得不实现一个 Button,我需要它在被按下 5 秒后触发。

为此,我创建了一个附加行为。我有五秒钟的时间回到行为中,因为我不需要这个可配置但很容易用 Dependency Property 完成的,并且它以 Command 的方式与 MVVM 一起使用,但是它可以轻松更改为触发 Click

    <Button Command="{Binding Path=ButtonCommand}">
        <i:Interaction.Behaviors>
            <behaviors:PressAndHoldBehavior />
        </i:Interaction.Behaviors>
    </Button>

public sealed class PressAndHoldBehavior : Behavior<Button>
{
    private DispatcherTimer dispatcherTimer;

    protected override void OnAttached()
    {
        dispatcherTimer = new DispatcherTimer {Interval = TimeSpan.FromSeconds(5)};
        dispatcherTimer.Tick += OnDispatcherTimerTick;
        AssociatedObject.PreviewMouseLeftButtonDown += AssociatedObjectPreviewMouseLeftButtonDown;
        AssociatedObject.PreviewMouseLeftButtonUp += AssociatedObjectPreviewMouseLeftButtonUp;
    }

    protected override void OnDetaching()
    {
        dispatcherTimer.Stop();
        dispatcherTimer.Tick -= OnDispatcherTimerTick;
        dispatcherTimer = null;
        AssociatedObject.PreviewMouseLeftButtonDown -= AssociatedObjectPreviewMouseLeftButtonDown;
        AssociatedObject.PreviewMouseLeftButtonUp -= AssociatedObjectPreviewMouseLeftButtonUp;
    }

    private void AssociatedObjectPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        dispatcherTimer.Start();
        e.Handled = true;
    }

    private void AssociatedObjectPreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        dispatcherTimer.Stop();
        e.Handled = true;
    }

    private void OnDispatcherTimerTick(object sender, EventArgs e)
    {
        AssociatedObject.Command.Execute(null);
    }
}