#c# #.net #observable #system.reactive
Вопрос:
У меня есть кнопка WPF в .NET, и я хочу обрабатывать события щелчка и двойного щелчка отдельно. В настоящее время я работаю над этим, используя тайм-ауты/задержки, и это работает, но это некрасиво. Я пытаюсь найти простой способ сделать это с помощью системы.Реактивные расширения для .NET
Наблюдаемые объекты создаются из заводского метода, в котором я передаю кнопку, и я использую метод FromEventPattern(кнопка, «щелчок»). например:
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");
}
Проблема в том, что когда я подписываюсь на эти наблюдаемые, срабатывает одиночный щелчок как для одного, так и для двойного щелчка.
Как сделать так, чтобы это работало по назначению, чтобы при двойном щелчке срабатывал одиночный щелчок, а не один.
Ответ №1:
Решение, которое я придумал, заключается в привязке к событиям щелчка мыши в обоих примерах и размещении событий в буфере 350ms. А затем отфильтруйте на основе числа событий, произошедших за период времени 350 мс.
Для события с одним щелчком мы ожидаем, что в буфере будет событие с одним щелчком, а для события с двойным щелчком мы ожидаем, что будет ровно 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-это мой собственный класс, замените его предупреждением или другим методом вывода для тестирования.
Комментарии:
1. Я бы предложил добавить a
.Publish(xs => xs.Buffer(() => xs.Throttle(TimeSpan.FromMilliseconds(350.0))))
, чтобы предотвратить возможность нескольких подписок на ваш источник.