【问题标题】:ContextMenu position is unpredictable when I'm trying to show same instance of menu more than once当我尝试多次显示相同的菜单实例时,ContextMenu 的位置是不可预测的
【发布时间】:2025-12-15 22:20:14
【问题描述】:

我需要在特定位置显示ContextMenu,它第一次就可以正常工作。如果我移动鼠标光标并尝试显示相同的ContextMenu,那么它可能会显示在不同的位置,即使HorizontalOffsetVerticalOffset 是硬编码的。

如何在特定位置打开ContextMenu而不每次都重新初始化?

System.Windows.Controls.Input.Toolkit 版本:5.0.5.0

XAML

<Grid x:Name="LayoutRoot" Background="White"
      MouseRightButtonUp="LayoutRoot_MouseRightButtonUp"
      MouseRightButtonDown="LayoutRoot_MouseRightButtonDown"/>

代码

private ContextMenu menu;

private void LayoutRoot_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
    if (menu == null)
    {
        menu = new ContextMenu();
        menu.Items.Add("test");
    }

    menu.HorizontalOffset = 100;
    menu.VerticalOffset = 100;

    menu.IsOpen = true;
}

private void LayoutRoot_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    e.Handled = true;
}

【问题讨论】:

    标签: silverlight contextmenu silverlight-toolkit


    【解决方案1】:

    上下文菜单中似乎存在错误。它不会在第一次单击时拾取鼠标指针位置。

    这里有一个解决方法:

    private void LayoutRoot_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
    {
        if (menu == null)
        {
            menu = new ContextMenu();
            menu.Items.Add("test");
            menu.HorizontalOffset = 100;
            menu.VerticalOffset = 100;
        }
        else
        {
            menu.HorizontalOffset = 100 - e.GetPosition(null).X;
            menu.VerticalOffset = 100 - e.GetPosition(null).Y;                
        }
    
        menu.IsOpen = true;
    }
    

    更新:

    我仔细查看了反汇编的源代码,似乎一旦显示了 ContextMenu,就启用了 MouseTracking,这就是为什么我们需要调整偏移量以抵消 ContextMenu 尝试调整其位置的影响最后一个 mousemove 事件,而不是最后一个 MouseRightButtonUp 位置。这是一个修改后的代码示例来说明它:

    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
    
            LayoutRoot.MouseRightButtonDown += LayoutRoot_MouseRightButtonDown;
            LayoutRoot.MouseRightButtonUp += LayoutRoot_MouseRightButtonUp;
            LayoutRoot.MouseMove += LayoutRoot_MouseMove;
            SetupContextMenu();
        }
    
        private void SetupContextMenu()
        {
            if (menu == null)
            {
                menu = new ContextMenu();
                menu.Items.Add("test");
                ContextMenuService.SetContextMenu(this, menu);
            }
    
        }
    
        private ContextMenu menu;
    
        private void LayoutRoot_MouseMove(object sender, MouseEventArgs e)
        {
            var mousePosition = e.GetPosition(this);
            menu.HorizontalOffset = 100 - mousePosition.X;
            menu.VerticalOffset = 100 - mousePosition.Y;
        }
    
        private void LayoutRoot_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            menu.IsOpen = true;
        }
    
        private void LayoutRoot_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
        }
    }
    

    【讨论】:

    • 感谢您的回答,但很遗憾,这并不能解决问题。您可以按照以下步骤重现它: 1. 右键单击​​任意位置以打开上下文菜单; 2、左键关闭; 3.在左上角(100x100 px)随机右键,上下文菜单位置会不一致。
    最近更新 更多