我正在寻找类似于jQuery throttle/debounce的东西,但是对于Silverlight。我们想在我们的Silverlight应用程序中去除选择更改事件 - 因此,如果用户快速连续快速更改选择,我们只会在用户停止更改时对更改做出反应。
我认为这并不难写,而且我不是在寻找示例代码 - 只是想知道这是否已经内置或在某些公共库中可用。如果没有,我将使用DispatcherTimer自行推送。
谢谢,
理查德
答案 0 :(得分:2)
事件限制并非内置于silverlight中。在您开始实施自己的版本之前,我会先看看reactive extensions for silverlight。其中一个函数被称为:Throttle,它就是它的名字所暗示的。我对反应式扩展的唯一问题是dll有点大,所以如果你必须让xap文件变小,你可能想要使用自己的实现。
答案 1 :(得分:0)
Reactive Extensions功能非常强大,但我不得不为项目推出自己的功能。这是:
using System.Timers;
public static class EventExtensions {
static Dictionary<EventHandler, Timer> _debounceTimers;
public static EventHandler Debounce(TimeSpan interval, Action<object, EventArgs> action) {
object lastSender = null;
EventArgs lastArgs = null;
var timer = new Timer();
if (_debounceTimers == null)
_debounceTimers = new Dictionary<EventHandler, Timer>();
timer.Interval = interval.TotalMilliseconds;
timer.Elapsed += (sender, args) => {
timer.Enabled = false;
timer.Stop();
action(lastSender, lastArgs);
};
EventHandler handler = (sender, args) => {
lastSender = sender;
lastArgs = args;
timer.Stop();
timer.Start();
timer.Enabled = true;
};
_debounceTimers.Add(handler, timer);
return handler;
}
public static void DisposeDebouncers(this EventHandler handler) {
handler.ThrowIfNull("handler");
if (_debounceTimers.ContainsKey(handler)) {
var timer = _debounceTimers[handler];
if (timer != null) {
timer.Stop();
timer.Enabled = false;
timer.Dispose();
}
}
}
}
using Xunit;
public class EventExtensionsTest {
event EventHandler FrequentEvent;
[Fact]
void DebounceTest() {
var counter = 0;
var span = TimeSpan.FromSeconds(1);
var handler = EventExtensions.Debounce(span, (sender, e) => counter++);
FrequentEvent += handler;
FrequentEvent(this, null);
FrequentEvent(this, null);
FrequentEvent(this, null);
Thread.Sleep(2000);
Assert.Equal(1, counter);
FrequentEvent(this, null);
FrequentEvent(this, null);
FrequentEvent(this, null);
FrequentEvent(this, null);
FrequentEvent(this, null);
Thread.Sleep(2000);
Assert.Equal(2, counter);
FrequentEvent.DisposeDebouncers();
FrequentEvent -= handler;
}
}
object.ThrowIfNull()
是一个扩展方法,如果对象为null,则抛出ArgumentNullException。我确信有无法发现的边缘情况。