2011-03-08 75 views
2

我知道,有一個簡單的方法來做到這一點 - 但它已經打敗我今晚......無框架/的DoubleClick

我想知道,如果發生在彼此的300毫秒的兩個事件,如在雙擊。

在300毫秒內點擊兩次鼠標左鍵 - 我知道這就是響應式框架的構建 - 但該死的如果我能找到一個好的文檔,其中包含所有擴展操作的簡單示例 - Throttle,BufferWithCount,BufferWithTime - all其中just werent'正在爲我做...

回答

9

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

非常感謝,我從我認爲是一件非常簡單的事情中學到了很多東西。哪裏有所有這些各種擴展的完整文檔?你是如何學習它們的? 我唯一的問題是關於重複,因爲我很困惑,當觀察者超出範圍(害羞而不是UnSubscribe)?如果我在我的課程的構造函數中訂閱,範圍是如何建立的?我知道OnComplete會調用dispose,但是在什麼時候正在監聽事件實際完成? – codeputer 2011-03-08 15:59:10

+0

你什麼時候使用Zip? – codeputer 2011-03-08 15:59:28

+0

@codputer - 我的大部分知識來自於我在將框架移植到actionscript時針對每個操作員編寫單元測試的事實。我記錄了大部分操作員,雖然他們已經過時了(我知道Throttle文檔是錯誤的) - https://github.com/richardszalay/rxas/wiki/Operators – 2011-03-08 20:37:58

3

編輯 - 使用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)); 
} 
+0

謝謝以及 - 我接近你打電話的答案,但認爲FastSubject有趣的是,確保所有來到在同一線程上的事件。雖然+1了! 我很好奇你在哪裏瞭解到Reactive Framework,以及所有各種擴展的文檔來源。 – codeputer 2011-03-08 16:01:06

+0

@codputer - 我想你誤會了。我的示例使用'FastSubject',因爲不需要線程處理(即鼠標點擊總是來自UI線程)。這是正常的Subject實現,可防止來自多個線程的值進入。 – 2011-03-08 20:35:47