Handling related actions

Oct 11, 2010 at 2:07 PM


I was just wondering what the stance is on defining actions that are not directly coupled to existing events. For instance, if I have a canvas on which I have some items. To drag an item, I need to handle the MouseDown, MouseMove and MouseUp events. I need to explictly handle these events instead of wrapping the handling in a Result, because the events are independent (though very strongly related).

What would be the recommended way to handle actions that are composed of multiple events?

Oct 11, 2010 at 3:15 PM
Edited Oct 11, 2010 at 3:15 PM

I've struggled a lot with this scenario, and I still haven't got a completely satisfactory solution.
The best I could do is to build an helper object and hook it, in the view side, to the set of events needed to identify a complete user interaction.
This helper object, in turn, exposes a single, task-oriented event, which actually triggers a single VM actions.

Does it make sense for you?

Oct 11, 2010 at 3:19 PM

It makes sense, but you would still only be triggering a single action, I think? Whereas in my scenario you'd have a sequence of events that show up (i.e. MouseDown once, MouseMove many times, MouseUp once).

Basically, you'd almost have this concept of an IEnumerable<Action>.

Oct 11, 2010 at 4:43 PM
Edited Oct 11, 2010 at 4:44 PM

Let me elaborate a bit.
I had this problem with a MS Surface application: in order to handle a *single* logical operation (from the user POV) I had to hook multiple coordinated event handler in the view.
This handlers (similarly to those regarding drag&drop) are needed to:

- decide if a "potential" gesture is actually executed
- understand WHICH gesture in a set is executed
- set up some visual feedback during the execution of a complex gesture
- receive notification of actual execution

I noticed that most of these are view-related concerns, so it would be definitely clumsy to handle them in VM as actions; plus, I would have needed to pass a bunch of UI-specific parameter to them (which I strongly try to avoid).

I ended up writing a view-side helper taking care of this mess, without involving the VM.

I only needed the intervention of VM logic in a couple moments: during the execution of a gesture (to decide whether an action was applicable or not according to business logic) and at the end of it (to actually start the business operation). So I created a couple events intended to communicate with the VM, just like I usually do with events from buttons.



Oct 11, 2010 at 5:25 PM

Yes, I see what you mean. Basically, you had an action that was 'invoked' by a certain combination of events (forming the gesture).

In my case though, the actions itself is alive during the events. In other words: It is not invoked at the end of a chain of events like your gesture-based action. Rather, its lifetime is the combined lifetime of all the events that form it.

Hm, I hope this is a bit clear.

Oct 13, 2010 at 1:23 AM

Sorry, I noticed your reply just now. 

I may have misunderstood your scenario, but I can still see a classic d&d process like a gesture. 
It is composed by a series of elementary mouse activity (mouse down, mouse move, mouse up) that you have to handle in a coordinated way.
But this handling is mostly done (usually) to accomplish UI concerns: the "functional" purpose of the whole user interaction is just to indicate that a particular domain object (the one whose visual representation is being dragged) has to be somewhat "activated" when the interaction ends.

So, the main purpose of my solution was to free up the VM from handling a bunch of input events that it don't really care about.
Even if you *really* need the intervention of the VM during the whole process (do you?), I still see advantages in letting the view to "digest" the user interaction and expose to the VM a "simplified" (and business-oriented) version of the underlying input events; this way the VM doesn't have to deal with pixels, controls, mouse buttons and other UI concerns.

I would love to hear alternative approaches, though :-)

Oct 13, 2010 at 8:13 AM

Well, I have to agree your approach makes the most sense, I think!

I'm just a bit 'annoyed' by the fact that business and UI concerns are intermingled like this. If I consider the moving of an item on a canvas, there are these concerns:

- If I move a single item, the selection service needs to be notified to deselect other items

- Once it is moved, I want to notify the undo service that there has been a movement

- When doing a "rectangular marquee" type selection (i.e. drag a box and everything inside is considered selected), then the selection service actually needs to know the physical size of the items so it can determine which items fall within the marquee.

I am sure that I can find a way to handle this by just exposing a "New Coordinates For Item" event from the view to the VM and handling the rest of the logic in the view, kind of :)