如何在WPF中使用ContextMenu UserControl?

7

我有一个用户控件,就像这样:

<UserControl x:Class="MyApp.UserControls.MyContextMenu"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d"
             ContextMenuOpening="OnContextMenuOpening"
             d:DesignHeight="300" d:DesignWidth="300">

    <UserControl.ContextMenu>
        <ContextMenu>
        ...
        </ContextMenu>
    </UserControl.ContextMenu>
</UserControl>

我的问题是: 如何在类似数据网格的情况下使用上下文菜单:
<DataGrid ContextMenu="{usercontrols:MyContextMenu}"

很遗憾,这不起作用是因为指定的值不正确,需要一个ContextMenu

注意: 我需要在几个地方重复使用我的上下文菜单,所以我把它放在了自己的文件中。此外,我需要能够监听OnContextMenuOpening事件,因为打开菜单时需要对菜单做一些工作,但不幸的是此事件并不能为上下文菜单触发:http://connect.microsoft.com/VisualStudio/feedback/details/353112/contextmenu-opening-event-doesnt-fire-properly

"ContextMenu本身是一个派生自FrameworkElement的类,但该事件将不会从打开为源的上下文菜单引发。该事件是从“拥有”上下文菜单的属性的元素引发的,并且仅在用户尝试在UI中打开上下文菜单时才引发。"

这个事件问题是我将菜单放在用户控件中的原因--这样用户控件可以获取事件并执行工作。

更新: 我试图将其作为根元素并扩展上下文菜单:

enter image description here

代码后台:

enter image description here

但我得到了:ContextMenu cannot have a logical or visual parent

2个回答

8
无论你如何调用你的UserControl,它都不是一个ContextMenu。你需要从ContextMenu派生出来:ContextMenu
<ContextMenu x:Class="MyApp.MyContextMenu"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <MenuItem Header="Item 1"/>
    <MenuItem Header="Item 2"/>
    ...
</ContextMenu>

并且

public partial class MyContextMenu : ContextMenu
{
    public MyContextMenu()
    {
        InitializeComponent();
    }
}

但为什么你会这样做呢?这句话的意思是询问为什么要这样做,具体情境需要根据上下文理解。

对我来说不起作用。它抱怨 ContextMenu 不能有逻辑或视觉父级。也就是说,上下文菜单只能用于 UI 元素的 ContextMenu 属性值,而不能作为元素使用。这还有另一个问题:我无法监听 OnContextMenuOpening 事件。 - Tower
不知道父级应该从哪里来。如果您查看我的XAML和代码,您会看到一个派生自ContextMenu的类。根本没有UserControl!这可以在任何需要ContextMenu的地方使用。当然,您必须在某个地方使用它,否则它就毫无意义了。 - Clemens
  1. 我需要在多个地方重用上下文菜单。
  2. 我需要监听 OnContextMenuOpening 事件并对打开的菜单进行一些操作。不幸的是,菜单从未触发该事件 - 只有放置目标。请参见:http://connect.microsoft.com/VisualStudio/feedback/details/353112/contextmenu-opening-event-doesnt-fire-properly
- Tower
为什么不覆盖 ContextMenu.OnOpened,或者已经太晚了? - Clemens
我创建了一个类似的用户控件,根元素为'ContextMenu',而不是用户控件。当我使用<DataGrid ContextMenu="{usercontrols:MyContextMenu}"时,我得到了预期类型为'ContextMenu'的错误。我是否漏掉了什么? - Carbine
显示剩余6条评论

5
尝试这样定义它:
<DataGrid.Resources>
    <ContextMenu x:Key="DgContextMenu">
      ...
    </ContextMenu>
</DataGrid.Resources>

并在使用时像这样使用

<DataGrid ContextMenu="{StaticResource DgContextMenu}

应该可以工作。


你的意思是说,因为它是用户控件而不是资源,所以我不能为其定义一个键,还是可以呢? - Tower
@rFactor:如果您想要精确地使用用户控件中的一个,是的话,您可以定义菜单作为静态资源,并在两个控件上使用它。 - Tigran
似乎这样做有些迂回,你可以直接定义“DataGrid.ContextMenu”,而不是“DataGrid.Resources”,并将资源指定为“ContextMenu”属性。 - Matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接