我知道,有一個簡單的方法來做到這一點 - 但它已經打敗我今晚......無框架/的DoubleClick
我想知道,如果發生在彼此的300毫秒的兩個事件,如在雙擊。
在300毫秒內點擊兩次鼠標左鍵 - 我知道這就是響應式框架的構建 - 但該死的如果我能找到一個好的文檔,其中包含所有擴展操作的簡單示例 - Throttle,BufferWithCount,BufferWithTime - all其中just werent'正在爲我做...
我知道,有一個簡單的方法來做到這一點 - 但它已經打敗我今晚......無框架/的DoubleClick
我想知道,如果發生在彼此的300毫秒的兩個事件,如在雙擊。
在300毫秒內點擊兩次鼠標左鍵 - 我知道這就是響應式框架的構建 - 但該死的如果我能找到一個好的文檔,其中包含所有擴展操作的簡單示例 - Throttle,BufferWithCount,BufferWithTime - all其中just werent'正在爲我做...
的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));
}
謝謝以及 - 我接近你打電話的答案,但認爲FastSubject有趣的是,確保所有來到在同一線程上的事件。雖然+1了! 我很好奇你在哪裏瞭解到Reactive Framework,以及所有各種擴展的文檔來源。 – codeputer 2011-03-08 16:01:06
@codputer - 我想你誤會了。我的示例使用'FastSubject',因爲不需要線程處理(即鼠標點擊總是來自UI線程)。這是正常的Subject實現,可防止來自多個線程的值進入。 – 2011-03-08 20:35:47
非常感謝,我從我認爲是一件非常簡單的事情中學到了很多東西。哪裏有所有這些各種擴展的完整文檔?你是如何學習它們的? 我唯一的問題是關於重複,因爲我很困惑,當觀察者超出範圍(害羞而不是UnSubscribe)?如果我在我的課程的構造函數中訂閱,範圍是如何建立的?我知道OnComplete會調用dispose,但是在什麼時候正在監聽事件實際完成? – codeputer 2011-03-08 15:59:10
你什麼時候使用Zip? – codeputer 2011-03-08 15:59:28
@codputer - 我的大部分知識來自於我在將框架移植到actionscript時針對每個操作員編寫單元測試的事實。我記錄了大部分操作員,雖然他們已經過時了(我知道Throttle文檔是錯誤的) - https://github.com/richardszalay/rxas/wiki/Operators – 2011-03-08 20:37:58