Reactive Framework / DoubleClick

我知道有一种简单的方法可以做到这一点 - 但它今晚打败了我...... 我想知道两个事件是否在300毫秒之内发生,就像双击一样。 在300毫秒内点击两次左击鼠标 - 我知道这就是反应框架的构建 - 但是如果我能找到一个包含所有扩展操作系统的简单示例的好文档 - Throttle,BufferWithCount,BufferWithTime - 所有这些都不是'为我做这件事......     
已邀请:
TimeInterval
方法将为您提供值之间的时间。
public static IObservable<Unit> DoubleClicks<TSource>(
    this IObservable<TSource> source, TimeSpan doubleClickSpeed, IScheduler scheduler)
{
    return source
        .TimeInterval(scheduler)
        .Skip(1)
        .Where(interval => interval.Interval <= doubleClickSpeed)
        .RemoveTimeInterval();
}
如果你想确保三次点击不会触发值,你可以在热的可观察量上使用
Repeat
(我在这里使用了
FastSubject
,因为点击将全部出现在一个线程上,因此不需要沉重的正常人):
public static IObservable<TSource> DoubleClicks<TSource>(
    this IObservable<TSource> source, TimeSpan doubleClickSpeed, IScheduler scheduler)
{
    return source.Multicast<TSource, TSource, TSource>(
        () => new FastSubject<TSource>(), // events won't be multithreaded
        values =>
        {
            return values
                .TimeInterval(scheduler)
                .Skip(1)
                .Where(interval => interval.Interval <= doubleClickSpeed)
                .RemoveTimeInterval()
                .Take(1)
                .Repeat();
        });
}
    
编辑 - 改为使用
TimeInterval()
Zip() and Timestamp()
运营商可能是一个良好的开端。
var ioClicks = Observable.FromEvent<MouseButtonEventHandler, RoutedEventArgs>(
                                        h => new MouseButtonEventHandler(h),
                                        h => btn.MouseLeftButtonDown += h,
                                        h => btn.MouseLeftButtonDown -= h);
var ioTSClicks = ioClicks.Timestamp();

var iodblClicks = ioTSClicks.Zip(ioTSClicks.Skip(1), 
                                 (r, l) => l.Timestamp - r.Timestamp)
                            .Where(tspan => tspan.TotalMilliseconds < 300);
可能最好通过测试调度程序对此进行测试,因此您确切地知道您正在获得的内容:
[Fact]
public void DblClick()
{
    // setup
    var ioClicks = _scheduler.CreateHotObservable(
                     OnNext(210, "click"),
                     OnNext(220, "click"),
                     OnNext(300, "click"),
                     OnNext(365, "click"))
                     .Timestamp(_scheduler);

    // act
    Func<IObservable<TimeSpan>> target = 
        () => ioClicks.Zip(ioClicks.Skip(1), 
                          (r, l) => l.Timestamp - r.Timestamp)
                        .Where(tspan => tspan.Ticks < 30);
    var actuals = _scheduler.Run(target);

    // assert
    Assert.Equal(actuals.Count(), 1);
    // + more
}
public static Recorded<Notification<T>> OnNext<T>(long ticks, T value)
{
    return new Recorded<Notification<T>>(
        ticks, 
        new Notification<T>.OnNext(value));
}
    

要回复问题请先登录注册