2010-12-03 6 views
2

Reactive Extensions for .NET을 WPF와 함께 사용하는 방법을 천천히 배우고 있습니다. 끌어서 놓기 또는 그리기 루틴을 작성하는 것이 얼마나 간단한 지에 대한 몇 가지 초보자 예가 있지만 모두 매우 간단합니다. 한 걸음 더 나아가려고 노력하고 있는데, "적절한"방법이 무엇인지는 분명하지 않습니다.Rx를 사용하여 마우스 끌기의 끝을 결정하는 적절한 방법은 무엇입니까?

의 예는 모두 당신이 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"); 

MouseDown, MouseMove에서 이벤트의 흐름을 정의하고 방법을 보여줍니다 당신은 쉽게 MouseDrag (이 사각형의 좌표를 표시하는 동안 일을 할 수있는 방법 현재 마우스 위치)

var mouseDrag = from start in mouseDown 
       from currentPosition in mouseMoves.TakeUntil(mouseUp) 
       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)); 

mouseDrag.Subscribe(x => 
      { 
       Info.Text = x.ToString(); 
      }); 

내 질문은, 마우스 드래그의 끝에서 작업을 수행하기 위해 "적절한"방법은 무엇으로 시작 드래그 지점에서 생성? 하지만, 더 이상 데이터가 (지금까지) 때 개체가 배치되지 수있을 때 onCompleted가 호출 될 것 같습니다, 문서의 더 읽기

mouseDrag.Subscribe(
    onNext: x => 
      { 
       Info.Text = x.ToString(); 
      }, 
    onCompleted:() => 
       { 
       // Do stuff here...except it never gets called 
       }); 

: 원래, 나는 같은 것을 할 수 있다고 생각.

그럴듯한 첫 번째 옵션은 mouseUp 이벤트에 가입하고 거기에서 뭔가하는 것입니다.

mouseUp.Subscribe(x => 
      { 
       // Do stuff here.. 
      } 

그러나이 시점에서, 나뿐만 아니라 다시 단지로 이동 "정상"MouseLeftButtonUp 이벤트 핸들러를 사용할 수 있습니다.

mouseDrag이 "완료"(또는 TakeUntil(mouseUp)) 될 때를 확인하고 몇 가지 작업을 수행 할 다른 방법이 있습니까?

답변

5

소스 (MouseDown)가 완료되지 않으므로 시퀀스가 ​​완료되지 않습니다 (이벤트). 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); 
} 

그런 다음과 같이 사용할 수 있습니다 :

element.TrackDrag(
    rect => { }, 
    () => {} 
); 

을 관심 여기에 기본 확장 메서드를 사용하는 LINQ식이 있습니다.

return mouseDown.SelectMany(start => 
{ 
    return mouseMove 
     .TakeUntil(mouseUp) 
     .Do(_ => {},() => dragComplete()) 
     .Select(currentPosition => new Rect(...)); 
}) 
.Subscribe(dragging); 

즉, mouseDown의 각 값에 대해 새 시퀀스가 ​​구독됩니다. 시퀀스가 ​​완료되면 dragComplete()를 호출하십시오.

+0

예 - 처음 시도한 후에 OnCompleted 방식이 작동하지 않는다는 것을 알았습니다. 더 완전한 설명과 Do()를 포함 해 주셔서 감사합니다. – Jedidja

관련 문제