WPF:按钮单击+双击问题

17

我需要在WPF应用程序中处理按钮的单击和双击事件,并进行不同的反应。

不幸的是,在双击时,WPF会触发两次单击事件和一个双击事件,因此很难处理这种情况。

我尝试使用计时器来解决问题,但没有成功……希望您能帮助我。

以下是代码:

private void delayedBtnClick(object statInfo)
{
    if (doubleClickTimer != null)
        doubleClickTimer.Dispose();
    doubleClickTimer = null;

    this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new VoidDelegate(delegate()
    {
        // ... DO THE SINGLE CLICK ACTION
    }));
}

private void btn_Click(object sender, RoutedEventArgs e)
{
    if (doubleClickTimer == null)
        doubleClickTimer = new Timer(delayedBtnClick, null, System.Windows.Forms.SystemInformation.DoubleClickTime, Timeout.Infinite);
        }
    }
}

private void btnNext_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    if (doubleClickTimer != null)
        doubleClickTimer.Change(Timeout.Infinite, Timeout.Infinite);    // disable it - I've tried it with and without this line
        doubleClickTimer.Dispose();
    doubleClickTimer = null;

    //.... DO THE DOUBLE CLICK ACTION
}
问题是在双击后,“DOUBLE CLICK ACTION”之后调用了“SINGLE CLICK ACTION”。奇怪的是,在双击时我将“doubleClickTimer”设置为null,但在“delayedBtnClick”中它却为true :O
我已经尝试过使用更长的时间、布尔标志和锁定…… 你有什么建议吗?
祝好!
2个回答

17
如果在处理MouseDoubleClick事件后将RoutedEvente.Handled设置为true,那么第二次MouseDoubleClick之后就不会调用Click事件了。
有一篇最近的文章提到了为SingleClickDoubleClick设置不同的行为,这可能很有用。
但是,如果您确定要使用单独的行为并且需要阻止第一次和第二次Click,则可以像以前一样使用DispatcherTimer
private static DispatcherTimer myClickWaitTimer = 
    new DispatcherTimer(
        new TimeSpan(0, 0, 0, 1), 
        DispatcherPriority.Background, 
        mouseWaitTimer_Tick, 
        Dispatcher.CurrentDispatcher);

private void Button_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    // Stop the timer from ticking.
    myClickWaitTimer.Stop();

    Trace.WriteLine("Double Click");
    e.Handled = true;
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    myClickWaitTimer.Start();
}

private static void mouseWaitTimer_Tick(object sender, EventArgs e)
{
    myClickWaitTimer.Stop();

    // Handle Single Click Actions
    Trace.WriteLine("Single Click");
}

非常感谢!e.Handled = true 就是关键!再次感谢您的快速反应 :) - Hunsoul
1
如果您使用DispatcherTimer的那个构造函数,计时器将立即启动,这将导致一个虚假的单击事件。此外,Background和Current是默认值,会使事情变得有些混乱(尽管可能存在一些巫术!)。非常有用 - 干杯! - JonnyRaa
我在代码中没有看到DoubleClickTime的使用,而是看到了一个硬编码的延迟。这正常吗? - SandRock
1
如果有人正在寻找一种自定义行为,允许在元素上设置单击和双击命令,请参阅此代码示例(它采用类似的基于计时器的方法,等待查看是否在SystemInformation.DoubleClickTime内有第二次单击)。 - JayChase

7
你可以尝试这个方法:
Button.MouseLeftButtonDown += Button_MouseLeftButtonDown;

private void Button_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    e.Handled = true;

    if (e.ClickCount > 1)
    {
        // Do double-click code
    }

    else
    {
        // Do single-click code
    }
}

如果必要,您可以要求鼠标点击并等待鼠标松开以执行操作。


谢谢你的回答!我还没有尝试过,因为第一个建议已经解决了我的问题 - 但再次感谢你! :) - Hunsoul
3
我尝试了这个方法,效果非常好。希望这个评论对其他人有所帮助。谢谢 Josh。 - akjoshi
1
这不会影响第一个单击事件,因为对于第一个单击事件 e.ClickCount = 1。 - Knasterbax
这应该怎么运行呢?该事件在第一次鼠标按下后被触发。无论之后你做什么,e.ClickCount总是等于1。使用C#的WPF。 - user2799180
不建议在鼠标抬起之前计算点击,因为这会阻止用户取消点击。 - Skarllot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接