1

我有以下

var leftMouseDown = Observable.FromEvent<MouseButtonEventArgs>(displayCanvas, "MouseLeftButtonDown");
var leftMouseUp = Observable.FromEvent<MouseButtonEventArgs>(displayCanvas, "MouseLeftButtonUp");
var mouseMove = Observable.FromEvent<MouseEventArgs>(displayCanvas, "MouseMove");

var leftMouseDragging = from down in leftMouseDown
                        let startPoint = down.EventArgs.GetPosition(displayCanvas)
                        from move in mouseMove.TakeUntil(leftMouseUp)
                        let endPoint = move.EventArgs.GetPosition(displayCanvas)
                        select new { Start = startPoint, End = endPoint };

当我订阅它时,它将给我拖动的起点和当前的终点。现在,一旦拖动完成,我需要做一些事情。我试图用 RX 完全做到这一点并没有成功,最后我做了

leftMouseDragging.Subscribe(value=>
    {
        dragging = true;
        //Some other code
    });

leftMouseUp.Subscribe(e=>
    {
        if(dragging)
        {
            MessageBox.Show("Just finished dragging");
            dragging = false;
        }
    });

这工作正常,直到我进行鼠标右键拖动。然后当我单击鼠标左键时,我得到消息框。如果我只拖动左键,我会得到消息框,然后单击鼠标左键不会产生该框。我想在没有外部状态的情况下这样做,但如果没有别的,我至少希望它能够正常工作。

仅供参考:我尝试使拖动变得易变并使用锁,但这没有用。

编辑

事实证明我的问题是右键单击上下文菜单。一旦我摆脱了上面的代码就可以了。所以,现在我的问题是如何获得上下文菜单并仍然让我的代码工作。我假设上下文菜单正在处理鼠标左键单击,并且不知何故导致我的代码无法正常工作,但我仍然对此感到困惑。

4

1 回答 1

5

如果您只需要拖动,那么简单的 .Zip 文件不会起作用吗?:

var drag = _mouseDown
    .Select(args => args.EventArgs.GetPosition(canvas))
    .Zip(_mouseUp.Select(args => args.EventArgs.GetPosition(canvas)), 
        (p1, p2) => new { p1, p2 });
drag.Subscribe(p1p2 => 
        Console.WriteLine(@"({0}:{1})({2}:{3})", 
            p1p2.p1.X, p1p2.p1.Y, p1p2.p2.X, p1p2.p2.Y));

如果您需要排除零长度拖动,您可以应用 Where 过滤器。

编辑:不过,Zip 很容易在窗口外释放鼠标 - 在这种情况下,除非您捕获,否则您不会获得 mouseUp... 这是在 mouseUp 之前仅使用最新 mouseDown 的版本:

var drag = _mouseDown
    .Select(args => args.EventArgs.GetPosition(canvas))
    .TakeUntil(_mouseUp)
    .CombineLatest(_mouseUp
        .Select(args => args.EventArgs.GetPosition(canvas))
        .Take(1), (p1, p2) => new { p1, p2 })
    .Repeat();
于 2010-04-25T01:25:25.750 回答