2

I have an application which has a drawing surface, where actions the user takes correlate strongly to the position of the mouse cursor. For the sake of example, let's say I'm trying to implement paste. In this case, the pasted data should be placed roughly in the center of the viewport from the user's prospective.

However, a concept like a "viewport" is a view concern, not a viewmodel concern. But the action to paste is a viewmodel concern, not a view concern.

How should this scenario be designed for MVVM systems?

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
Billy ONeal
  • 104,103
  • 58
  • 317
  • 552

1 Answers1

3

Since there is no mouse position property you can bind (for which you would use Mode=OneWayToSource), you could listen to the MouseMove event:

    private void OnMouseMove(object sender, MouseEventArgs e)
    {
        myViewModel.MousePosition = e.GetPosition(this);
    }

Before you say that's not MVVM because it uses code-behind, from http://msdn.microsoft.com/en-us/library/gg405484(v=pandp.40).aspx

In some cases, the code-behind may contain UI logic code that implements visual behavior that is difficult or inefficient to express in Extensible Application Markup Language (XAML), such as complex animations, or when the code needs to directly manipulate visual elements that are part of the view. You should not put any logic code in the view that you need to unit test. Typically, logic code in the view's code-behind will be tested via a UI automation testing approach.

As pointed out another method could be to use a CallMethodAction to bind event invocations to a call a method on your ViewModel:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity
xmlns:ei="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactions


<i:Interaction.Triggers>
    <i:EventTrigger EventName="MouseMoved">
        <ei:CallMethodAction TargetObject={Binding} MethodName="OnMouseMoved"/>
     </i:EventTrigger>
</i:Interaction.Triggers>

However I prefer not to use a binding here as the event will be raised very frequently and a binding will involve more overhead.

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
markmnl
  • 11,116
  • 8
  • 73
  • 109
  • Or maybe use an Event Trigger with CallMethodAction? That would at least transmit the mouse event to the view model. – McGarnagle Oct 24 '13 at 00:24
  • I'm not sure I get this whole "all code must be in the viewmodel" -- after all, that's not how things like Button and friends are implemented. Either solution here looks good. Thanks! +1 for now, still curious what other answers are posted for now. – Billy ONeal Oct 24 '13 at 02:10