使用 Reactive.NET RX 处理 Click 和 Double Click

Posted

技术标签:

【中文标题】使用 Reactive.NET RX 处理 Click 和 Double Click【英文标题】:Handling both Click and Double Click using Reactive.NET RX 【发布时间】:2021-11-06 04:07:45 【问题描述】:

我在 .NET 中有一个 WPF 按钮,我希望分别处理单击和双击事件。我目前已经使用超时/延迟来完成这项工作,它可以工作,但它很难看。我正在尝试找到一种使用 System.Reactive .NET 扩展的巧妙方法

Observables 是从我传递按钮的工厂方法创建的,我使用 FromEventPattern(button, "click") 方法。例如:

    public IObservable<EventPattern<RoutedEventArgs>> SingleClickTestObservable(Button button)
    
        return Observable.FromEventPattern<RoutedEventArgs>(button, "Click");
    

    public IObservable<EventPattern<RoutedEventArgs>> DoubleClickTestObservable(Button button)
    
        return Observable.FromEventPattern<RoutedEventArgs>(button, "DoubleClick");
    

问题是当我订阅这些 Observables 时,SingleClick 会同时触发单击和双击。

怎样才能让它按预期工作,这样当双击被触发时,单击就不会了。

【问题讨论】:

【参考方案1】:

我想出的解决方案是绑定到两个示例中的点击事件,并将事件放入一个 350 毫秒的缓冲区中。然后根据 350ms 时间段内发生的事件数进行过滤。

对于单击事件,我们希望缓冲区中有 1 个单击事件,而对于双击事件,我们希望恰好有 2 个:

    public IObservable<EventPattern<RoutedEventArgs>> DoubleClickTestObservable(Button button)
    
        var observable = Observable.FromEventPattern<RoutedEventArgs>(button, "Click");
        var bufferedObservable = observable.Buffer(observable.Throttle(TimeSpan.FromMilliseconds(350)))
            .Select(list => new  list.Count, list )
            .Where(result => result.Count == 2)
            .Select(x => x.list.Last());
        return bufferedObservable;

    

    public IObservable<EventPattern<RoutedEventArgs>> SingleClickTestObservable(Button button)
    
        var observable = Observable.FromEventPattern<RoutedEventArgs>(button, "Click");
        var bufferedObservable = observable.Buffer(observable.Throttle(TimeSpan.FromMilliseconds(350)))
            .Select(list => new  list.Count, list )
            .Where(result => result.Count == 1)
            .Select(x => x.list.Single());
        return bufferedObservable;
    

用法:

var button = GetMyButton();         
var singleClickSub = DoubleClickTestObservable(button)
    .Subscribe(pattern =>  _logger.Debug("got double click"); );
var doubleClickSub = SingleClickTestObservable(button)
    .Subscribe(pattern =>  _logger.Debug("got single click"); );

注意:_logger是我的一个自定义类,替换为alert,或者其他输出方式进行测试。

【讨论】:

我建议添加 .Publish(xs =&gt; xs.Buffer(() =&gt; xs.Throttle(TimeSpan.FromMilliseconds(350.0)))) 以防止多次订阅您的 observable 源。

以上是关于使用 Reactive.NET RX 处理 Click 和 Double Click的主要内容,如果未能解决你的问题,请参考以下文章

处理 RX 中的 response.body == null

反应式框架(RX)和异步处理事件

typescript RX-处理器

使用 Rx 无限重复异常

华擎发布 RX 6900 XT 非公显卡:5120 流处理器,三风扇散热

卡在 Rx Observable SelectMany