Как составить RX.Net Наблюдаемые для взаимодействия с перетаскиванием мыши?

#c# #observable #reactive-programming #system.reactive #rx.net

#c# #наблюдаемые #реактивное программирование #система.реактивная #rx.net

Вопрос:

Я хочу использовать RX, чтобы включить режим перетаскивания мыши для выделения областей на графике. (Оксиплот) Должна быть возможность выбрать несколько областей на графике, и они должны быть текущим обновлением выбранной области.

До сих пор я настроил три наблюдаемых объекта из событий:

 var mouseDownObservable = Observable.FromEventPattern<OxyMouseDownEventArgs>(tmp, nameof(tmp.MouseDown))
            .Where(e => e.EventArgs.ChangedButton == OxyMouseButton.Left)
            .Where(e => e.EventArgs.IsControlDown == true);
var mouseMoveObservable = Observable.FromEventPattern<OxyMouseEventArgs>(tmp, nameof(tmp.MouseMove));
var mouseUpObservable = Observable.FromEventPattern<OxyMouseEventArgs>(tmp, nameof(tmp.MouseUp));
 

Я новичок в RX, так что моя первая попытка была:

 var result = mouseDownObservable
                .Select(m => m.EventArgs.Position)
                .Merge(mouseMoveObservable
                .SkipUntil(mouseDownObservable.Select(e => e.EventArgs.Position).Do(e1 =>
                {
                    // .. create annotation in plot
                }))
                .TakeUntil(mouseUpObservable)
                .Select(m => m.EventArgs.Position)
                .Repeat());
                .CombineLatest(mouseDownObservable.Select(e => e.EventArgs.Position),
                        (endPoint, startPoint) => new List<ScreenPoint>() { endPoint, startPoint })
                .Do(e =>
                {
                    // .. update actual annotation to current endPoint
                })
                .Subscribe();
 

Я не знал, как сохранить состояние (начальная точка наведения курсора мыши), поэтому я решил использовать combineLatest.

Сначала я выбираю область, которая работает довольно хорошо. Если я хочу выбрать другую область, я получаю правильную начальную точку (d1), но конечная точка по-прежнему является последним элементом (r). Диаграмма из мрамора

  1. Каков хороший подход к сохранению информации о начальной точке? Я чувствую себя немного неуклюжей из-за этого.
  2. Как я могу сгруппировать результат так, чтобы было ровно одно mouseDragObservable для каждого комбинированного взаимодействия перетаскивания мыши?

Ответ №1:

Я думаю, ты немного переусердствовал.

Вот запрос, который вам нужен:

 var deltas =
    from down in mouseDownObservable
    from move in mouseMoveObservable.TakeUntil(mouseUpObservable)
    select new
    {
        X = move.EventArgs.Position.X - down.EventArgs.Position.X,
        Y = move.EventArgs.Position.Y - down.EventArgs.Position.Y
    };
 

Таким образом, это просто ожидание нажатия мыши вниз, а затем запись всех движений, которые происходят после этого, пока мышь не будет поднята. Итак, по сути, операция перетаскивания.

Потому что первая часть from down in mouseDownObservable — это то, что у вас есть запись X Y координат / во время нажатия мыши. Затем очень легко создать серию дельт координат на основе положения во время каждого перемещения.

Комментарии:

1. Спасибо за ваш быстрый ответ, это было очень полезно. Да, я тоже думаю, что я слишком много думал об этом. 🙂