代码之家  ›  专栏  ›  技术社区  ›  juharr

使用反应式扩展创建可观察的鼠标拖动

  •  1
  • juharr  · 技术社区  · 16 年前

    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;
            }
        });
    

    在我用鼠标右键拖动之前,这一切都很正常。然后,当我点击鼠标左键时,我会看到消息框。如果我只做一个左键拖动,我会得到消息框,然后单击鼠标左键不会生成消息框。我希望在没有外部状态的情况下执行此操作,但如果没有其他情况,我至少希望它能够正常工作。

    编辑

    原来我的问题是右键单击上下文菜单。一旦我摆脱了它,我上面的代码就工作了。所以,现在我的问题是,我如何获得上下文菜单,并且仍然让我的代码工作。我假设上下文菜单处理的是鼠标左键点击,这不知何故导致了我的代码无法工作,但我仍然很困惑。

    1 回复  |  直到 16 年前
        1
  •  5
  •   Sergey Aldoukhov    16 年前

    如果你只需要拖拽,那么简单的.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));
    

    编辑:不过,Zip很容易在窗口外释放鼠标-在这种情况下,除非您捕获到。。。 以下版本仅使用鼠标按下前的最新鼠标按下:

    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();