什么是结构化的最佳途径这一LINQ到活动拖放放大器;删除code? [英] What's the best way to structure this Linq-to-Events Drag & Drop code?

查看:101
本文介绍了什么是结构化的最佳途径这一LINQ到活动拖放放大器;删除code?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想处理一个拖放放大器;下降的相互作用,它涉及按下鼠标,鼠标移动和鼠标了。

I am trying to handle a drag & drop interaction, which involves mouse down, mouse move, and mouse up.

下面是我的解决方案的简化摄制的:

Here is a simplified repro of my solution that:

  • 在按下鼠标,创建一个椭圆形,并把它添加到画布
  • 在鼠标移动,重新定位椭圆跟随鼠标
  • 在鼠标向上,改变了画布的颜色,这样很明显哪一个你拖动。

  • on mouse down, creates an ellipse and adds it to a canvas
  • on mouse move, repositions the ellipse to follow the mouse
  • on mouse up, changes the colour of the canvas so that it's obvious which one you're dragging.

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"/>

有几件事我不喜欢这个code,我需要帮助重构吧:)

There's a few things I don't like about this code, and I need help refactoring it :)

首先:在MouseDown和MouseUp回调被指定为副作用。如果两个订阅制成,它们会发生两次。

First of all: the mousedown and mouseup callbacks are specified as side effects. If two subscriptions are made to q, they will happen twice.

二,指定鼠标松开回调的的鼠标移动的回调。这使得它有点难以阅读。

Second, the mouseup callback is specified before the mousemove callback. This makes it a bit hard to read.

第三,参照椭圆似乎是一个愚蠢的地方。如果有两个订阅,该变量引用将得到很快覆盖。我敢肯定,应该有一些方法,我们可以利用关键字引入一个变量LINQ EX pression这将意味着正确的椭圆参考,请这两个鼠标移动和鼠标了处理程序

Thirdly, the reference to the ellipse seems to be in a silly place. If there's two subscriptions, that variable reference will get overwritten quite quickly. I'm sure that there should be some way we can leverage the let keyword to introduce a variable to the linq expression that will mean the correct ellipse reference is available to both the mouse move and mouse up handlers

你会如何写这code?

How would you write this code?

推荐答案

要避免subscrition副作用,你应该公布你的观测。我想,这样的事情是确定:

To avoid subscrition side-effects, you should publish your observable. I think something like this would be Ok:

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

这篇关于什么是结构化的最佳途径这一LINQ到活动拖放放大器;删除code?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆