I'm developing a WPF application with the MVVM pattern, RelayCommand, etc. I read a lot on this question but I am not clear as to:
All I want to do is move a shape, like an ellipse, for example, and capture its final position, to put in the database.
But I can't bind events (MouseLetButtonDown, MouseLeftButtonUp and MouseMove) to commands. I've read about attached behaviours , but I need the arguments of the events (MouseButtonEventArgs and MouseEventArgs) to retrieve the position.
Solution?
When writing an MVVM graphical application, it is tempting to try to send all the events you need over to the view-model. But processing view-specific mouse event args in a command is contrary to MVVM principles and the goal of loose-coupling.
The way to solve this problem is to abstract the operation into a task that the view can perform and then to communicate its results back to the view-model via operations and data. If you want to perform a small amount of code in the code-behind to support this, the MVVM police will not come and take your children. But an even better way is to add interactivity with behaviors. Behaviors are re-usable pieces of functionality with no code-behind that work well with the MVVM pattern and applications that need interactivity that would otherwise require adding event handlers to your XAML.
See my answer here for a complete example of a behavior that uses mouse events for dragging graphical objects:
With your interactivity performed by the view, the view-model can stick to data and commands.
This works for Silverlight so it should work on WPF (or at least it should with minor modifications)
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<cmd:EventToCommand Command="{Binding MouseCommand, PassEventArgsToCommand="True", CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
You can find XCommand open source codeplex wpf extention project here, xcommand.codeplex.com, this allows you to bind Command and CommandParameter of any events like MouseMove, MouseLeftButtonDown to any UI elements that inherits from WPF UIElement.
You can find windows store 8 application and windows desktop application version of class libraries here. You want WPFXCommand that deals with WPF desktop application. Here, how it works. Add WPFXCommand.dll as reference to your desire project.
Add the namespace on your xaml file as below:
xmlns:XCmd="clr-namespace:WPFXCommand;assembly=WPFXCommand"
Now, you can bind Command and CommandParameter to any available events on any UI elements inherit from WPF UIElement as below:
<Grid>
<TextBlock Margin="20,30,20,0" VerticalAlignment="Top" Height="80" x:Name="XTextBlock"
Foreground="{Binding FgColor, Mode=TwoWay}"
XCmd:MouseMove.Command="{Binding TextBlockPointerMovedCommand}"
XCmd:MouseLeftButtonDown.Command="{Binding TextBlockPointerPressedCommand}"
XCmd:MouseLeave.Command="{Binding TextBlockPointerExitedCommand}"
Text="{Binding Description, Mode=TwoWay}">
</TextBlock>
<Grid Grid.Column="1" Background="{Binding BgColor, Mode=TwoWay}"
XCmd:MouseMove.Command="{Binding GridPointerMovedCommand}"
XCmd:MouseMove.CommandParameter="{Binding ElementName=XTextBlock, Path=Text}"
XCmd:MouseLeftButtonDown.Command="{Binding GridPointerPressedCommand}"
XCmd:MouseLeftButtonDown.CommandParameter="{Binding ElementName=XTextBlock, Path=Text}"
>
</Grid>
</Grid>
Hope this will help you to get rid of event based code behind.
来源:https://stackoverflow.com/questions/4785685/wpf-and-mvvm-binding-events