Reactive Drag and Drop Part 2

Reactive Programming, Posting # 7

In Part 1 of this 2 part posting we looked at capturing the mouse movements.  The key code in Part 1 was,

var q = from start in mousedown
        from pos in mousemove.StartWith( start )
        .TakeUntil( mouseup )
        select pos;

Now, in part 2, rather than just getting the coordinates of the mouse, we want to find the delta so that we can move the image with the changes in the mouse position. 

Part 1 was written for WPF, but as was pointed out by Jim Wooley in a comment on part 1, the same code can be written for Silverlight or Windows Phone by modifying the MouseDown to MouseLeftButtonDown and MouseUp to MouseLeftButtonUp.

For Windows Phone, make sure that you add a reference to Microsoft Phone Reactive and to System Observable and for ths program, you’ll need to ensure that you have using statements for Microsoft.Phone.Reactive, System.Windows.Input, System.Windows.Controls and System.Linq.

We’ll begin by redefining mouseDown and MouseUp

var mousedown = from evt in Observable.FromEvent
                   <MouseButtonEventArgs>(
                   image, "MouseLeftButtonDown" )
                select evt.EventArgs.GetPosition( image );
var mouseup = from evt in Observable.FromEvent
                 <MouseButtonEventArgs>(
                 this, "MouseLeftButtonUp" )
              select evt.EventArgs.GetPosition(
              this );

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

Notice that mousedown and mouseup use the MouseLeftButtonDown and MouseLeftButtonUp events, respectively and that mousedown sets the image as the source of the event

We are using a select statement on mouseup, but the truth is we don’t care about the mouse position, just the fact that the event was fired, so we can simplify this middle definition to

var mouseup = Observable.FromEvent
        <MouseButtonEventArgs>(
        this, "MouseLeftButtonUp" );

 

Our query statement becomes one of finding the start position and end position  (for each movement of the mouse while the button is down) and then subtracting the end from the start to get the change in position for the image.

var q = from start in mousedown
        from end in mousemove.TakeUntil( mouseup )
        select new
        {
           X = end.X - start.X,
           Y = end.Y - start.Y
        };

 

We can then use that query to subscribe to the mouse as if it were an observable  collection of points. 

q.Subscribe( value =>
{
   Canvas.SetLeft( image, value.X );
   Canvas.SetTop( image, value.Y );
} );

Note that image is the name of the Image object defined in Xaml.

 

The net effect is that if you click on the image, you can drag it around the phone’s canvas until you release the mouse button.

About Jesse Liberty

Jesse Liberty has three decades of experience writing and delivering software projects and is the author of 2 dozen books and a couple dozen online courses. His latest book, Building APIs with .NET will be released early in 2025. Liberty is a Senior SW Engineer for CNH and he was a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Microsoft MVP.
This entry was posted in Linq, Mini-Tutorial, Reactive, WindowsPhone and tagged , , . Bookmark the permalink.