Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Rx确定鼠标拖动结束的正确方法是什么?_C#_Wpf_.net 4.0_System.reactive - Fatal编程技术网

C# 使用Rx确定鼠标拖动结束的正确方法是什么?

C# 使用Rx确定鼠标拖动结束的正确方法是什么?,c#,wpf,.net-4.0,system.reactive,C#,Wpf,.net 4.0,System.reactive,我正在慢慢学习如何使用WPF。这里有一些初学者的例子,说明编写拖放或绘图例程是多么简单,但它们都非常简单。我正试图更进一步,但我并不清楚什么是“正确的”方式 这些示例都显示了如何从MouseDown、MouseMove和MouseUp定义事件流 var mouseDown = from evt in Observable.FromEvent<MouseButtonEventArgs>(..., "MouseDown") select evt.Event

我正在慢慢学习如何使用WPF。这里有一些初学者的例子,说明编写拖放或绘图例程是多么简单,但它们都非常简单。我正试图更进一步,但我并不清楚什么是“正确的”方式

这些示例都显示了如何从
MouseDown
MouseMove
MouseUp
定义事件流

var mouseDown = from evt in Observable.FromEvent<MouseButtonEventArgs>(..., "MouseDown")
                select evt.EventArgs.GetPosition(...);

var mouseMoves = from evt in Observable.FromEvent<MouseEventArgs>(..., "MouseMove")
                 select evt.EventArgs.GetPosition(...);

var mouseUp = Observable.FromEvent<MouseButtonEventArgs>(..., "MouseUp");
我的问题是,在鼠标拖动结束时完成任务的“正确”方式是什么?最初,我认为我可以做这样的事情:

mouseDrag.Subscribe(
     onNext: x =>
             {
                 Info.Text = x.ToString();
             },
     onCompleted: () =>
              {
                 // Do stuff here...except it never gets called
              });
尽管阅读了更多的文档,但是当没有更多的数据(曾经)并且对象可以被释放时,似乎调用了
onCompleted

因此,第一个似乎可用的选项是订阅
mouseUp
事件并在那里做一些事情

mouseUp.Subscribe(x =>
           {
              // Do stuff here..
           }
但是在这一点上,我还是回到使用“普通”的MouseLeftButtonUp事件处理程序


是否有另一种方法可以确定何时“完成”鼠标拖动(或何时发生“鼠标拖动”(mouseUp))并执行某些操作?

序列永远不会完成,因为源(鼠标向下)永远不会完成(这是一个事件)。值得指出的是,
IObservable
不能多次调用订户的
OnComplete
,这是合同的一部分(
OnNext*(OnCompleted | OnError)?

要了解
mouseMove.TakeUntil(mouseUp)
序列何时完成,您需要挂接调用
SelectMany

public static IDisposable TrackDrag(this UIElement element, 
    Action<Rect> dragging, Action dragComplete)
{
    var mouseDown = Observable.FromEvent(...);
    var mouseMove = Observable.FromEvent(...);
    var mouseUp = Observable.FromEvent(...);

    return (from start in mouseDown
            from currentPosition in mouseMove.TakeUntil(mouseUp)
                    .Do(_ => {}, () => dragComplete())
            select new Rect(Math.Min(start.X, currentPosition.X),
                            Math.Min(start.Y, currentPosition.Y),
                            Math.Abs(start.X - currentPosition.X),
                            Math.Abs(start.Y - currentPosition.Y));
            ).Subscribe(dragging);
}
为了清楚起见,以下是使用底层扩展方法的LINQ表达式:

return mouseDown.SelectMany(start =>
{
    return mouseMove
        .TakeUntil(mouseUp)
        .Do(_ => {}, () => dragComplete())
        .Select(currentPosition => new Rect(...));
})
.Subscribe(dragging);
也就是说,对于mouseDown中的每个值,将订阅一个新序列。当该序列完成时,调用dragComplete()。

Yes——我在第一次尝试失败后意识到,未完成的方式不是可行的方式。感谢您提供更完整的解释,包括Do():)
element.TrackDrag(
    rect => { },
    () => {}
);
return mouseDown.SelectMany(start =>
{
    return mouseMove
        .TakeUntil(mouseUp)
        .Do(_ => {}, () => dragComplete())
        .Select(currentPosition => new Rect(...));
})
.Subscribe(dragging);