I would use an attached behaviour here. This will allow you to continuously monitor the mouse position, rather than simply responding to an event such as MouseDown. You'll need to add a reference to the System.Windows.Interactivity
assembly.
The code below provides a simple example of this in action.
XAML
<Window x:Class="MouseMoveMvvm.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:mouseMoveMvvm="clr-namespace:MouseMoveMvvm"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock Text="{Binding PanelX, StringFormat='X={0}'}" />
<TextBlock Text="{Binding PanelY, StringFormat='y={0}'}" />
</StackPanel>
<Canvas DockPanel.Dock="Bottom" Background="Aqua">
<i:Interaction.Behaviors>
<mouseMoveMvvm:MouseBehaviour MouseX="{Binding PanelX, Mode=OneWayToSource}" MouseY="{Binding PanelY, Mode=OneWayToSource}" />
</i:Interaction.Behaviors>
</Canvas>
</DockPanel>
</Grid>
</Window>
Note that, in the above XAML, the MouseBehaviour is pushing the mouse position down to the ViewModel through a OneWayToSource binding, while the two TextBlocks are reading the mouse positions from the ViewModel.
ViewModel
public class MainWindowViewModel : INotifyPropertyChanged
{
private double _panelX;
private double _panelY;
public event PropertyChangedEventHandler PropertyChanged;
public double PanelX
{
get { return _panelX; }
set
{
if (value.Equals(_panelX)) return;
_panelX = value;
OnPropertyChanged();
}
}
public double PanelY
{
get { return _panelY; }
set
{
if (value.Equals(_panelY)) return;
_panelY = value;
OnPropertyChanged();
}
}
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Attached Behaviour
public class MouseBehaviour : System.Windows.Interactivity.Behavior<FrameworkElement>
{
public static readonly DependencyProperty MouseYProperty = DependencyProperty.Register(
"MouseY", typeof (double), typeof (MouseBehaviour), new PropertyMetadata(default(double)));
public double MouseY
{
get { return (double) GetValue(MouseYProperty); }
set { SetValue(MouseYProperty, value); }
}
public static readonly DependencyProperty MouseXProperty = DependencyProperty.Register(
"MouseX", typeof(double), typeof(MouseBehaviour), new PropertyMetadata(default(double)));
public double MouseX
{
get { return (double) GetValue(MouseXProperty); }
set { SetValue(MouseXProperty, value); }
}
protected override void OnAttached()
{
AssociatedObject.MouseMove += AssociatedObjectOnMouseMove;
}
private void AssociatedObjectOnMouseMove(object sender, MouseEventArgs mouseEventArgs)
{
var pos = mouseEventArgs.GetPosition(AssociatedObject);
MouseX = pos.X;
MouseY = pos.Y;
}
protected override void OnDetaching()
{
AssociatedObject.MouseMove -= AssociatedObjectOnMouseMove;
}
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…