WPF MenuItem.Click 在育儿后中断

标签 wpf events click menuitem

我正在尝试使用各种 MenuItem(均在代码中创建)动态填充 Menu 控件(驻留在 ControlTemplate 中),但我遇到了一些奇怪的问题。如果 MenuItems 都作为根项创建,它们会成功触发它们的 Click 事件。但是一旦任何 MenuItem 成为另一个 MenuItem 的子项,父项和子项的 Click 事件都会停止触发。

XAML:

<ControlTemplate>
    <Menu x:Name="MyMenu"/>
</ControlTemplate>

C#:
// This is in the control that the above ControlTemplate is created for
public override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    MenuItem L1 = new MenuItem() { Header = "L1" };
    MyMenu.Items.Add(L1); // Add as root
    L1.Click += new RoutedEventHandler(delegate { MessageBox.Show("L1 Click"); });

    MenuItem L2 = new MenuItem() { Header = "L2" };
    L1.Items.Add(L2); // Add as child of L1.
    // Note: If this is a child of MyMenu, both MenuItems work as expected
    L2.Click += new RoutedEventHandler(delegate { MessageBox.Show("L2 Click"); });
}

菜单显示正确,但子项上的点击事件根本没有触发。如果我在 XAML 中预定义菜单并在 XAML 中设置所有 Click 事件,它可以完美运行 - 但它必须在代码中,所以这不是一个选项。此外,如果我将“L2”设为“MyMenu”的子项,即改为将其设为根项目,L1 和 L2 将再次开始工作 - 但我也无法将所有内容都作为根项目。
有什么我想念的吗?

谢谢!

编辑 1:

我尝试了一个小实验,以查看在将 L1 设为 L2 并添加它们的 Click 事件之前是否正确初始化了所有内容。仍然没有运气。这是我尝试过的:

XAML:
<ControlTemplate>
    <Grid>
        <Menu x:Name="MyMenu"/>
        <Button x:Name="MyButton"/>
    </Grid>
</ControlTemplate>

C#:
public override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    MenuItem L1 = new MenuItem() { Header = "L1" };
    MyMenu.Items.Add(L1);

    MenuItem L2 = new MenuItem() { Header = "L2" };
    MyMenu.Items.Add(L2); // Add this to the menu to make sure it gets initialised

    // I created a button so I can make sure that the parenting
    // and events are only added after the MenuItems are loaded
    MyButton.Click += new RoutedEventHandler(MyButton_Clicked);
}

void MyButton_Clicked(object sender, RoutedEventArgs e)
{
    // Note: If these two lines are removed, the events work fine
    MyMenu.Items.Remove(L2);
    L1.Items.Add(L2);

    L1.Click += new RoutedEventHandler(delegate { MessageBox.Show("L1 Click"); });
    L2.Click += new RoutedEventHandler(delegate { MessageBox.Show("L2 Click"); });
}

当 Window 加载并显示所有内容时,我单击 Button 以便进行育儿并添加事件。我看到 L2 作为 L1 的子级被移动,但是当我单击其中一个时,它们不响应 Click 事件。如果我阻止了育儿形式的发生,他们会响应 Click 事件。我很困惑为什么会这样!

编辑2:

我在一个干净的项目中复制了原始帖子中的所有内容,并且一切正常。所以这不是 Menu 或 MenuItems 或它们的使用方式的问题。这个问题的原因仍然未知......

编辑 3:

根据要求,我使用添加到 Window 的以下代码重新测试了这一点:
PreviewMouseLeftButtonDown += new MouseButtonEventHandler(delegate
{
    // Use Ctrl key to enable MessageBox so focus is not lost when opening menu
    if (Keyboard.Modifiers == ModifierKeys.Control)
        MessageBox.Show("Window PreviewMouseLeftButtonDown");
});

PreviewMouseLeftButtonDown 总是在按住 ctrl 单击“死”菜单项时触发。他们的 Click 事件在成为 parent 后继续停止工作。仍然没有解决方案或问题的迹象......

编辑 4:

我做了以下测试,为 L1 和 L2 添加以下代码:
L1.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(delegate
{
    MessageBox.Show("L1 PreviewMouseLeftButtonDown"); 
});
// Same for L2

当 Clicked 时,MenuItem L1 和 L2 都响应 PreviewMouseLeftButtonDown,但在成为父项后继续停止响应 Click。

最佳答案

我终于解开了这个谜。我将问题追溯到父控件在其中进行任何点击后窃取焦点,尽管奇怪的是菜单保持打开状态并对导航使用react,即使它没有焦点。随着对 Focus() 的调用被删除,一切似乎都有效。

发生的事情的细节:

菜单项育儿:

1)我点击一个根菜单项,它响应点击。

2) OnPreviewMouseDown 然后被父级拦截并调用 Focus()。

由于 Click 成功触发,在这种情况下没有出现因失去焦点而导致的不良结果。

菜单项育儿:

1)我点击菜单,它打开了。

2) OnPreviewMouseDown 然后被父级拦截并调用 Focus()。

3)菜单保持打开状态并继续对导航使用react(这是注定要发生的吗??)。

4) 当我第二次单击任何 MenuItem 进行选择时,菜单终于意识到它失去了焦点并关闭了 - 也放弃了单击。

然后似乎 MenuItem 进行了单击并丢弃了单击...导致原始帖子中遇到的问题。

关于WPF MenuItem.Click 在育儿后中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5596438/

相关文章:

wpf - 当其他列的内容折叠时,网格列不填充剩余空间

javascript - 如何从 onChange 事件获取非字母数字键的值是 JS/React

Javascript:是否可以在事件处理程序之外获取鼠标位置?

javascript - 复选框 onchange 事件未触发

JQuery的scrollTop函数转到正确的位置,但然后跳回页面顶部

image - 如何通过单击主图像打开 fotorama 全屏模式?

jquery - JavaScript/Jquery : replace click with on

c# - BitmapImage 与 ImageBrush 的性能

c# - Mahapps 1.3 对话框和 Avalon.Wizard

c# - WPF 绑定(bind) : cannot resolve symbol due to unknown datacontext