Reactive Drag and Drop Part 1

Reactive Programming, Posting # 4

Continuing the discussion of Reactive Programming, this posting, based on a video from the Rx team, will create and annotate Drag and Drop using the Rx toolkit.  In part 1 we’ll track mouse movements, in part 2 we’ll implement drag and drop on an image.

Applying reactive programming to mouse movements treats the mouse as an observable collection of points and allows you to subscribe to that collection so that as new points become available you are notified.

To get started, create a new WPF Application (because we want to play with mouse movements).

Replace the grid with a canvas, and on the canvas add a TextBlock and an Image.  .

<Canvas>
   <TextBlock Name="textBlock" Text="Rx Drag and Drop" />
   <Image
      Name="image"
      Source="d:\avatar.png"
      Width="100"
      Height="100"
      Canvas.Left="25"
      Canvas.Top="25" />

</Canvas>

Make sure you’ve installed the Rx for .NET 4 libraries (available here) and in this project add references to System.CoreEx and System.Reactive.

We want to observe the mouse down/up and move events. The syntax is to create a variable, and assign to that variable the observer that we’ll create from the event. The FromEvent construct takes the name of the event args, the object on which the event will be raised, and the name of the event.  We can then select what values we want.

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

We do the same with mouseup and mouse move

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

We can now create an observable that listens to the mouse positions from the time the mouse goes down and ending when the mouse goes up,

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

We can then subscribe to this observable and display the positions while the mouse button is down,

q.ObserveOnDispatcher()
   .Subscribe(
   value => textBlock.Text =
      value.ToString() );

The ObserveOnDispatcher forces back to the visual thread (so as not to throw an exception).

The subscribe method takes an Action, and so we can pass in a delegate to a method that assigns the string representation of the value to our text box.  In this case, as is customary we use a lambda expression to make the code easier to read and maintain.

Share

About Jesse Liberty

Jesse Liberty is an independent consultant and programmer with three decades of experience writing and delivering software projects. He is the author of 2 dozen books and multiple Pluralsight courses, and has been 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 Xamarin Certified Mobile Developer and a Xamarin MVP, Microsoft MVP and Telerik MVP.
This entry was posted in Mini-Tutorial, Patterns & Skills, Reactive and tagged . Bookmark the permalink.

7 Responses to Reactive Drag and Drop Part 1

  1. Pingback: Реализация поведения контролов в Silverlight | Немного о разработке

  2. Pingback: What are Reactive Extensions (Rx) - CodePB

  3. ian says:

    Ok, I figured out how to use it: I did the following. I also changed the subscription to actually move the image. not sure if I’ve done that the best way though.

    public partial class MainWindow : Window
    {
    private IObservable _q;

    public MainWindow()
    {
    InitializeComponent();
    StartRx();
    }

    private void StartRx()
    {
    var mousedown = from evt in Observable.FromEvent
    (
    this, “MouseDown”)
    select evt.EventArgs.GetPosition(
    this);

    var mouseup = from evt in Observable.FromEvent
    (
    this, “MouseUp”)
    select evt.EventArgs.GetPosition(
    this);
    var mousemove = from evt in Observable.FromEvent
    (
    this, “MouseMove”)
    select evt.EventArgs.GetPosition(
    this);

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

    _q.ObserveOnDispatcher()
    .Subscribe(
    value =>
    {
    textBlock.Text = value.ToString();
    Canvas.SetTop(image, value.Y);
    Canvas.SetLeft(image, value.X);
    });
    }
    }

  4. ian says:

    Ok, interesting but where exactly does the code go? Window’s load or something?

  5. Jose says:

    Jesse,

    I am using my Outlook RSS reader, and when I click on the “View Article” link, it redirect’s me to a malware site telling me “I have been infected and should download their antivirus.” Looks like your feedproxy has been hijacked?

  6. Jim Wooley says:

    Of course, this technique isn’t limited to WPF. It can be done with Silverlight 3 and above and WP7 just as easily changing the MouseDown with MouseLeftButtonDown to correspond to the different event name. I demonstrate the drag-drop support in my http://www.thinqlinq.com/Post.aspx/Title/Reactive-Extensions-responding-to-UI-events post and include downloadable samples as well.

  7. Pingback: Tweets that mention Reactive Drag and Drop Part 1 | Jesse Liberty -- Topsy.com

Leave a Reply

Your email address will not be published.