我试图处理一个拖拉的互动,其中涉及老鼠下,老鼠移动和鼠标。

这里是一个简化的重现我的解决方案:

  • 在鼠下,创建一个椭圆,并将它添加到画布
  • 在老鼠移动,重新定位椭圆遵循鼠
  • 在鼠,改变颜色的画布所以,这是显而易见的是哪一个你拖动。

    var mouseDown = Observable.FromEvent<MouseButtonEventArgs>(canvas, "MouseLeftButtonDown");
    var mouseUp = Observable.FromEvent<MouseButtonEventArgs>(canvas, "MouseLeftButtonUp");
    var mouseMove = Observable.FromEvent<MouseEventArgs>(canvas, "MouseMove");
    
    Ellipse ellipse = null;
    
    var q = from start in mouseDown.Do(x =>
                {
                    // handle mousedown by creating a red ellipse, 
                    // adding it to the canvas at the right position
                    ellipse = new Ellipse() { Width = 10, Height = 10, Fill = Brushes.Red };
                    Point position = x.EventArgs.GetPosition(canvas);
                    Canvas.SetLeft(ellipse, position.X);
                    Canvas.SetTop(ellipse, position.Y);
                    canvas.Children.Add(ellipse);
                })
            from delta in mouseMove.Until(mouseUp.Do(x =>
                {
                    // handle mouse up by making the ellipse green
                    ellipse.Fill = Brushes.Green;
                }))
            select delta;
    
    q.Subscribe(x =>
    {
        // handle mouse move by repositioning ellipse
        Point position = x.EventArgs.GetPosition(canvas);
        Canvas.SetLeft(ellipse, position.X);
        Canvas.SetTop(ellipse, position.Y);
    });
    

XAML是简单

    <Canvas x:Name="canvas"/>

有几件事情我不喜欢这个代码,我需要帮助的重构,它:)

首先:该mousedown和mouseup回被指定为副作用。如果两个订阅了 q, 他们会发生的两倍。

第二,mouseup回指定 之前 该鼠标移回调。这使得它有点难于阅读。

第三,参考椭圆似乎是在一个愚蠢的地方。如果有两个订阅,该变量的基准将得到复盖相当迅速。我敢肯定,应该有一些办法,我们可以利用 let 关键字来介绍一个变量来皇宫的表达,这将意味着正确的椭圆参考是提供给老鼠移动和老鼠了处理程序

你会怎么写这个代码?

有帮助吗?

解决方案

为了避免subscrition的副作用,应发布观察。我认为这样的事情将是确定:

        public MainWindow()
    {
        InitializeComponent();
        var mouseDown = Observable
            .FromEvent<MouseButtonEventArgs>(this, "MouseLeftButtonDown");
        var mouseUp = Observable
            .FromEvent<MouseButtonEventArgs>(this, "MouseLeftButtonUp");
        var mouseMove = Observable
            .FromEvent<MouseEventArgs>(this, "MouseMove");

        var ellipses = mouseDown
            .Select(args => new { 
                a = args, 
                el = new Ellipse
                {
                    Width = 10, Height = 10, Fill = Brushes.Red
                }})
            .Publish();

        ellipses
            .Subscribe(elargs =>
            {
                var position = elargs.a.EventArgs.GetPosition(canvas);
                Canvas.SetLeft(elargs.el, position.X);
                Canvas.SetTop(elargs.el, position.Y);
                canvas.Children.Add(elargs.el);
            });

        var elmove = from elargs in ellipses
                     from mm in mouseMove.TakeUntil(mouseUp)
                     select new { a = mm, el = elargs.el };

        elmove.
            Subscribe(elargs =>
            {
                var position = elargs.a.EventArgs.GetPosition(canvas);
                Canvas.SetLeft(elargs.el, position.X);
                Canvas.SetTop(elargs.el, position.Y);
            });

        var elmup = from elargs in ellipses
                    from mup in mouseUp
                    select elargs.el;

        elmup.Subscribe(el => el.Fill = Brushes.Green);

        ellipses.Connect();
    }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top