如何在视图模型中获取鼠标位置

从MVVM设计模式来看,viewmodel不应该知道视图。 但就我而言,我需要视图和模型,我的意思是:

在我的窗口中,我有一个Image组件。 当鼠标移过Image组件并将其保存到我的模型中时,我想获得鼠标位置。

背后的代码应该是:

void Foo_MouseMove(objet sender, MouseEventArgs e) { model.x = e.getPosition(this.imageBox).X; model.y = e.getPosition(this.imageBox).Y; } 

问题是:我需要this.imageBox和MouseEventArgs,所以两个View元素。

我的问题是:如何使用MVVM方法处理这种情况?

我使用MVVM轻量级框架

Finnally使用EventConverter找到答案:

  public class MouseButtonEventArgsToPointConverter : IEventArgsConverter { public object Convert(object value, object parameter) { var args = (MouseEventArgs)value; var element = (FrameworkElement)parameter; var point = args.GetPosition(element); return point; } } 

这个转换器允许我处理Point而不是图形组件。

这是XML:

       

我会在这里使用附加行为。 这将允许您连续监视鼠标位置,而不是简单地响应MouseDown等事件。 您需要添加对System.Windows.Interactivity程序集的引用。

下面的代码提供了一个简单的示例。

XAML

                

请注意,在上面的XAML中,MouseBehaviour通过OneWayToSource绑定将鼠标位置向下推到ViewModel,而两个TextBlock正在从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)); } } 

附加行为

 public class MouseBehaviour : System.Windows.Interactivity.Behavior { 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; } } 

Mark Greens解决方案是最好的(我发现)。

如果你想让他的解决方案可以重用任何WPF控件(我建议),inheritanceSystem.Windows.Interactivity.Behavior实际上不适用于Panel ,因为Panel不从Controlinheritance。 只有那些类inheritance自Control : https : //msdn.microsoft.com/de-de/library/system.windows.controls.control(v = vs.110).aspx

相反,inheritance自System.Windows.Interactivity.BehaviorFrameworkElement是所有WPF控件类的祖先: https : //msdn.microsoft.com/de-de/library/system.windows.frameworkelement(v=vs.110).aspx 。 我已经在GridPanelImage btw上进行了测试。

我使用它来保持Popup与鼠标光标同步:

        

PS:我会对解决方案发表评论,但我的回答太长了。