什么是最好的方式来构建这个Linq-to-Events Drag&删掉代码? [英] What's the best way to structure this Linq-to-Events Drag & Drop code?

查看:124
本文介绍了什么是最好的方式来构建这个Linq-to-Events Drag&删掉代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力处理拖累



以下是我的解决方案的简化修改:




  • 在鼠标下方,创建一个椭圆,并将其添加到画布上

  • ,鼠标移动,重新设置椭圆跟随鼠标

  • 在鼠标向上,更改画布的颜色,这样很明显你拖动哪一个。

      var mouseDown = Observable.FromEvent< MouseButtonEventArgs>(canvas,MouseLeftButtonDown); 
    var mouseUp = Observable.FromEvent< MouseButtonEventArgs>(canvas,MouseLeftButtonUp);
    var mouseMove = Observable.FromEvent< MouseEventArgs>(canvas,MouseMove);

    椭圆椭圆= null;

    var q = from mouseDown.Do(x =>
    {
    //通过创建一个红色椭圆来处理mousedown,
    //将其添加到画布在正确的位置
    ellipse = new Ellipse(){Width = 10,Height = 10,Fill = Brushes.Red};
    点位置= x.EventArgs.GetPosition(canvas);
    Canvas.SetLeft(ellipse,position.X);
    Canvas.SetTop(ellipse,position.Y);
    canvas.Children.Add(ellipse);
    })
    从delta在mouseMove.Until(mouseUp.Do(x =>
    {
    //通过使椭圆形绿色处理鼠标向上
    ellipse.Fill = Brushes.Green;
    }))
    选择delta;

    q.Subscribe(x =>
    {
    //通过重新定位椭圆来处理鼠标移动
    点位置= x.EventArgs.GetPosition(canvas);
    Canvas.SetLeft(ellipse,position.X);
    Canvas.SetTop(ellipse,position.Y);
    });




XAML只是简单的

 < Canvas x:Name =canvas/> 

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



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



其次,在 mousemove回调之前指定了mouseup回调。这使得它有点困难。



第三,对椭圆的引用似乎在一个愚蠢的地方。如果有两个订阅,该变量引用将被很快覆盖。我确定应该有一些方法,我们可以利用 let 关键字向linq表达式引入一个变量,这意味着正确的椭圆参考可用于鼠标移动和鼠标向上处理程序



你将如何编写代码?

解决方案

p>为了避免消耗副作用,你应该发布你的观察。我觉得这样的事情会很好:

  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
{
宽度= 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。
订阅(elargs =>
{
var position = elargs.a.EventArgs.GetPosition(canvas);
Canvas.SetLeft(elargs.el,position.X);
Canvas.SetTop(elargs.el,position.Y);
});

var elmup =从椭​​圆中的elargs
从鼠标中的mup
选择elargs.el;

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

ellipses.Connect();
}


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

the XAML is simply

    <Canvas x:Name="canvas"/>

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

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.

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

How would you write this code?

解决方案

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-to-Events Drag&amp;删掉代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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