如何获取WPF上下文菜单的原始右键点击坐标(无需手动弹出菜单)?
实现方案:无需手动弹出菜单,获取右键点击坐标作为命令参数
可以实现,不用接管控件的右键事件手动弹出菜单,以下是两种可行方案:
方案1:利用ContextMenu的Opening事件记录坐标
这种方式只需少量代码配合绑定即可实现:
- 在XAML中给ContextMenu添加Opening事件处理:
<ContextMenu x:Key="PolyCtxMenu" Opening="PolyCtxMenu_Opening"> <MenuItem Command="{Binding AddVertexCmd}" CommandParameter="{Binding RightClickPosition}" /> </ContextMenu>
- 在后台代码的Opening事件中,获取右键点击的相对坐标(以目标控件为基准),并赋值给ViewModel的属性:
private void PolyCtxMenu_Opening(object sender, RoutedEventArgs e) { var contextMenu = sender as ContextMenu; var targetControl = contextMenu.PlacementTarget as PolyControl; if (targetControl != null) { // 获取相对于PolyControl的鼠标坐标 var pos = Mouse.GetPosition(targetControl); // 假设你的ViewModel有一个名为RightClickPosition的Point类型属性 var vm = targetControl.DataContext as YourViewModel; vm.RightClickPosition = pos; } }
- 确保你的ViewModel中定义了
RightClickPosition属性(实现INotifyPropertyChanged):
private Point _rightClickPosition; public Point RightClickPosition { get => _rightClickPosition; set { _rightClickPosition = value; OnPropertyChanged(); } }
方案2:纯XAML绑定(利用附加属性)
如果希望尽量少写后台代码,可以通过自定义附加属性来捕获右键坐标:
- 创建一个附加属性类:
public static class MousePositionHelper { public static readonly DependencyProperty RightClickPositionProperty = DependencyProperty.RegisterAttached( "RightClickPosition", typeof(Point), typeof(MousePositionHelper), new PropertyMetadata(new Point())); public static Point GetRightClickPosition(DependencyObject obj) { return (Point)obj.GetValue(RightClickPositionProperty); } public static void SetRightClickPosition(DependencyObject obj, Point value) { obj.SetValue(RightClickPositionProperty, value); } // 监听控件的PreviewMouseRightButtonDown事件来记录坐标 public static readonly DependencyProperty TrackRightClickPositionProperty = DependencyProperty.RegisterAttached( "TrackRightClickPosition", typeof(bool), typeof(MousePositionHelper), new PropertyMetadata(false, OnTrackRightClickPositionChanged)); public static bool GetTrackRightClickPosition(DependencyObject obj) { return (bool)obj.GetValue(TrackRightClickPositionProperty); } public static void SetTrackRightClickPosition(DependencyObject obj, bool value) { obj.SetValue(TrackRightClickPositionProperty, value); } private static void OnTrackRightClickPositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var element = d as UIElement; if (element == null) return; if ((bool)e.NewValue) { element.PreviewMouseRightButtonDown += Element_PreviewMouseRightButtonDown; } else { element.PreviewMouseRightButtonDown -= Element_PreviewMouseRightButtonDown; } } private static void Element_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) { var element = sender as UIElement; if (element != null) { var pos = e.GetPosition(element); SetRightClickPosition(element, pos); } } }
- 在XAML中使用这个附加属性:
<PolyControl ContextMenu="{StaticResource PolyCtxMenu}" local:MousePositionHelper.TrackRightClickPosition="True" /> <ContextMenu x:Key="PolyCtxMenu"> <MenuItem Command="{Binding AddVertexCmd}" CommandParameter="{Binding PlacementTarget.(local:MousePositionHelper.RightClickPosition), RelativeSource={RelativeSource AncestorType=ContextMenu}}" /> </ContextMenu>
这种方式通过附加属性自动监听目标控件的右键按下事件,记录坐标,然后在MenuItem中通过RelativeSource绑定到PlacementTarget(即PolyControl)的附加属性值,无需手动处理菜单的Opening事件。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

