You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取WPF上下文菜单的原始右键点击坐标(无需手动弹出菜单)?

实现方案:无需手动弹出菜单,获取右键点击坐标作为命令参数

可以实现,不用接管控件的右键事件手动弹出菜单,以下是两种可行方案:

方案1:利用ContextMenu的Opening事件记录坐标

这种方式只需少量代码配合绑定即可实现:

  1. 在XAML中给ContextMenu添加Opening事件处理:
<ContextMenu x:Key="PolyCtxMenu" Opening="PolyCtxMenu_Opening">
    <MenuItem Command="{Binding AddVertexCmd}" 
              CommandParameter="{Binding RightClickPosition}" />
</ContextMenu>
  1. 在后台代码的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;
    }
}
  1. 确保你的ViewModel中定义了RightClickPosition属性(实现INotifyPropertyChanged):
private Point _rightClickPosition;
public Point RightClickPosition
{
    get => _rightClickPosition;
    set
    {
        _rightClickPosition = value;
        OnPropertyChanged();
    }
}

方案2:纯XAML绑定(利用附加属性)

如果希望尽量少写后台代码,可以通过自定义附加属性来捕获右键坐标:

  1. 创建一个附加属性类:
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);
        }
    }
}
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 14:06:23