有没有一种标准的方法可以去除Silverlight中的事件?

时间:2011-06-30 04:26:29

标签: .net silverlight events


我正在寻找类似于jQuery throttle/debounce的东西,但是对于Silverlight。我们想在我们的Silverlight应用程序中去除选择更改事件 - 因此,如果用户快速连续快速更改选择,我们只会在用户停止更改时对更改做出反应。

我认为这并不难写,而且我不是在寻找示例代码 - 只是想知道这是否已经内置或在某些公共库中可用。如果没有,我将使用DispatcherTimer自行推送。


谢谢,
理查德

2 个答案:

答案 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。我确信有无法发现的边缘情况。