-1

Win2D 具有此功能Invalidate(),调用时将重绘整个控件,并且在快速连续调用时,它们将合并为一个更新,其中包含先前调用的任何更改。我试图在我自己的应用程序中重新创建它,但我找不到与此描述完全匹配的框架。

假设每次我单击图表时,都会添加一条线。我想要发生的是,如果有人连续点击 100 次,它将等到点击完成后一次添加所有行,而不是一次添加一行。同样,调整窗口大小应该只重绘一次图表,而不是每次触发事件时。

我尝试过使用System.Reactive,但它们的大部分合并/节流似乎忽略了以前的调用,并且我不能OnCompleted()在事件上使用订阅的部分,因为它永远不会“完成”。

有没有人有解决这样的问题的经验?我正在寻找使用计时器来产生一种延迟,但我想知道是否已经有一些东西可以按照描述的方式工作。

4

3 回答 3

0

这在 Rx 中非常简单。这就是你需要的:

IObservable<long> query =
    source
        .Select(t => Observable.Timer(TimeSpan.FromMilliseconds(100.0)))
        .Switch();

因此,只要在用户执行操作sourceIObservable<T>产生一个值,那么这个 observable 将仅在100.0自上一个值以来有毫秒的非活动期时才会产生一个值。

现在,您可能想要整理一下,以便查询产生原始值并编组回调度程序。这也很容易。

尝试这个:

IObservable<T> query =
    source
        .Select(t =>
            Observable
                .Timer(TimeSpan.FromMilliseconds(100.0))
                .Select(_ => t))
        .Switch()
        .ObserveOnDispatcher();

简单的。

于 2018-01-28T06:24:31.003 回答
0

I have tried using System.Reactive, but most of their merging/throttling seems to ignore the previous calls, and I can't use the OnCompleted() part of Subscribe on an event as it does not ever "complete".

I think you missed some, like the Buffer operator:

Button button = new Button();

...

var subscription = button
    .ButtonClicks()
    .Buffer(TimeSpan.FromSeconds(0.5), 100) // Perform action  after 100 clicks or after half a second, whatever comes first
    .Select(buffer => buffer.Count)
    .Subscribe(clickCount =>
    {
        // Do something with clickCount
    })

The helper class:

public static class Extensions
{
    public static IObservable<EventPattern<RoutedEventArgs>> ButtonClicks(this Button control)
    {
        return Observable.FromEventPattern<RoutedEventHandler, RoutedEventArgs>(
                h => control.Click += h,
                h => control.Click -= h);
    }
}

At the end of the application:

subscription.Dispose();

Of course Buffer has some overloads:

Buffer(TimeSpan.FromSeconds(1)) -> Buffer for a second, then perform action (Same result as the accepted answer)

Buffer(100) -> Perform action after 100 clicks

于 2018-01-26T18:54:23.087 回答
-1

这是我解决这个问题的方法。为了便于理解,我将所有这些都放在 Mainwindow.xaml.cs 中,但您可能希望将逻辑移到它自己的类中。

    private int clickCount;
    private DateTime lastClick;
    private System.Windows.Threading.DispatcherTimer clickEventTimer;
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (clickEventTimer == null || !clickEventTimer.IsEnabled)
        {
            clickCount = 1;
            lastClick = DateTime.Now;
            clickEventTimer = new System.Windows.Threading.DispatcherTimer() { Interval = TimeSpan.FromSeconds(1) };
            clickEventTimer.Tick += (timer, args) =>
            {
                if (DateTime.Now - lastClick < TimeSpan.FromSeconds(1))
                {
                    return;
                }
                else
                {
                    clickEventTimer.Stop();
                    MessageBox.Show($"Do stuff for the {clickCount.ToString()} click(s) you got.");
                }
            };
            clickEventTimer.Start();
        }
        else
        {
            clickCount++;
            lastClick = DateTime.Now;
        }
    }
于 2018-01-26T15:43:29.340 回答