.net 构造此Linq to事件拖放代码的最佳方法是什么?

.net 构造此Linq to事件拖放代码的最佳方法是什么?,.net,drag-and-drop,c#-4.0,system.reactive,.net,Drag And Drop,C# 4.0,System.reactive,我正在尝试处理一个拖放交互,包括鼠标下移、鼠标移动和鼠标上移 以下是我的解决方案的简化副本: 按下鼠标,创建椭圆并将其添加到画布 移动鼠标时,重新定位椭圆以跟随鼠标 鼠标向上移动时,更改画布的颜色,以便可以清楚地看到正在拖动的画布 var mouseDown = Observable.FromEvent<MouseButtonEventArgs>(canvas, "MouseLeftButtonDown"); var mouseUp = Observable.FromEvent<

我正在尝试处理一个拖放交互,包括鼠标下移、鼠标移动和鼠标上移

以下是我的解决方案的简化副本:

按下鼠标,创建椭圆并将其添加到画布 移动鼠标时,重新定位椭圆以跟随鼠标 鼠标向上移动时,更改画布的颜色,以便可以清楚地看到正在拖动的画布

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进行两次订阅,则会发生两次

其次,在mousemove回调之前指定mouseup回调。这使得阅读起来有点困难

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


您将如何编写此代码?

为了避免订阅的副作用,您应该发布您的observable。我认为像这样的事情可以:

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

我喜欢它的阅读方式。你/我可以在哪里读到更多关于订阅和Connect@rob-关于MSDN的丰塞卡传感器反应性扩展论坛是目前唯一的地方。。。我们需要看到更多这样的问题。