且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

什么是正确的方法来确定接收使用鼠标拖动的结束?

更新时间:2023-11-25 11:01:04

该序列永远不会完成,因为源(的MouseDown)永远不会完成(这是一个事件)。值得指出的是,一个的IObservable 不能打电话的的onComplete 用户超过一次,这是合同的组成部分( OnNext *(OnCompleted |的OnError)

The sequence never completes because the source (MouseDown) never completes (it is an event). It's worth pointing out that a IObservable cannot call OnComplete of a subscriber more than once, it's part of the contract (OnNext* (OnCompleted|OnError)?).

要找出当 mouseMove.TakeUntil(mouseUp事件)序列完成后,你需要挂接到调用的SelectMany

To find out when themouseMove.TakeUntil(mouseUp) sequence completes, you'll need to hook into the call to SelectMany:

public static IDisposable TrackDrag(this UIElement element, 
    Action<Rect> dragging, Action dragComplete)
{
    var mouseDown = Observable.FromEvent(...);
    var mouseMove = Observable.FromEvent(...);
    var mouseUp = Observable.FromEvent(...);

    return (from start in mouseDown
            from currentPosition in mouseMove.TakeUntil(mouseUp)
                    .Do(_ => {}, () => dragComplete())
            select new Rect(Math.Min(start.X, currentPosition.X),
                            Math.Min(start.Y, currentPosition.Y),
                            Math.Abs(start.X - currentPosition.X),
                            Math.Abs(start.Y - currentPosition.Y));
            ).Subscribe(dragging);
}

然后你可以使用它像这样:

Then you can use it like so:

element.TrackDrag(
    rect => { },
    () => {}
);

有关为清楚起见,这里是使用底层的扩展方法的LINQ EX pression:

For the interest of clarity, here is the LINQ expression using the underlying extension methods:

return mouseDown.SelectMany(start =>
{
    return mouseMove
        .TakeUntil(mouseUp)
        .Do(_ => {}, () => dragComplete())
        .Select(currentPosition => new Rect(...));
})
.Subscribe(dragging);

即,对于从MOUSEDOWN每个值的新的序列将被预订。当的序列完成后,调用dragComplete()。

That is, for each value from mouseDown a new sequence will be subscribed to. When that sequence completes, call dragComplete().