我试图通过一些简单的挑战来学习Rx,首先通过观察MouseUp事件来检测双击。我提出了以下解决方案(该代码可以通过创建WPF项目并添加Reactive Extensions NuGet包来编译):
using System;
using System.Reactive.Linq;
using System.Windows.Input;
namespace WpfApplication1 {
public partial class MainWindow {
public MainWindow() {
InitializeComponent();
var clickEvents = Observable
.FromEventPattern<MouseButtonEventArgs>(this, "MouseLeftButtonUp");
var intraClickInterval = TimeSpan.FromMilliseconds(500);
var interClickInterval = TimeSpan.FromMilliseconds(1000);
var doubleClicks = clickEvents
.TimeInterval()
.SkipWhile(t => t.Interval < interClickInterval)
.FirstAsync(t => t.Interval < intraClickInterval)
.Repeat();
var doubleClickReady = doubleClicks
.Delay(interClickInterval)
.Subscribe(e => Console.WriteLine("Now accepting double click!"));
doubleClicks.Subscribe(e => Console.WriteLine(e.Interval));
}
}
}
我见过的大多数解决方案不处理多次点击,所以想法是每次双击之间总是等待一定的间隔(interClickInterval),然后双击是下一个鼠标向上事件,其间隔小于intraClickInterval。我还添加了一条消息,在每次双击后interClickInterval结束后打印,以便我知道何时应该注册双击。
这似乎在一般情况下工作得很好,但似乎有时他们不注册,即使我看到"现在接受双击!"消息。这似乎发生特别是如果我点击之前的消息出现。是什么原因造成的呢?
编辑:我认为双击检测实际上是正确的,这是不正确的消息。基本上,它忽略双击之后的任何后续单击。我需要做一些像
这样的东西- 每次双击事件
- 等待interClickInterval
- 如果没有点击注册,显示"现在接受双点击!"
所以正如我所怀疑的那样,检测代码是正确的,这是消息计时错误。它没有考虑双击之后的任何后续点击;它总是在每次双击后1000毫秒打印消息。下面是ready消息的一个版本,它正确地等待从每次双击后最后一次单击开始的1000ms时间:
var doubleClickReady = doubleClicks
.SelectMany(clickEvents
.Buffer(interClickInterval)
.FirstAsync(b => b.Count == 0));
doubleClickReady
.Subscribe(e => Console.WriteLine("Now accepting double click!"));