在CodeBehind中实现动态上下文菜单

13

我想为我动态创建的一些对象添加ContextMenu,但是我找到的唯一方法是像这样在运行时创建ContextMenu:

ContextMenu pMenu = new ContextMenu();
MenuItem item1  = new MenuItem();
MenuItem item2  = new MenuItem();

//I have about 10 items
//...
item1.Header = "item1";
item1.Click += new RoutedEventHandler(item1_Click);
pMenu.Items.Add(item1);

item2.Header = "item2";
item2.Click += new RoutedEventHandler(item2_Click);
pMenu.Items.Add(item2);

//and so on

它能运行,但是在WinForms中,我能够快速地将ContextMenuStrip组件拖放到我的表单上,并定义项目和事件,而无需编写任何代码。在WPF中是否也可能呢?

3个回答

31

你可以在资源中定义你的ContextMenu并将其绑定到任何你需要的控件上。看一下这个:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Window.Resources>
        <ContextMenu x:Key="MyContextMenu">
            <MenuItem Header="Send" />
        </ContextMenu>
    </Window.Resources>
    <Grid>
        <Button Name="a_button"
            ContextMenu="{StaticResource MyContextMenu}" >
        </Button>
    </Grid>
</Window>

1
好的,但我动态创建对象,那么如何在运行时绑定它? - Mike
@Michael:您应该能够通过 var pMenu = (ContextMenu)this.Resources["MyContextMenu"]; 在运行时获取ContextMenu。然后,您可以将此变量分配给动态创建的控件。 - Heinzi
谢谢,它有效。唯一我无法理解的是为什么在WPF中我必须做所有这些魔法,而没有适当的组件和GUI在IDE中使事情更容易,因为它们应该是。 - Mike
8
在WPF中,窗体不是你的应用程序,数据才是。这与WinForms非常不同,因为在WinForms中,窗体是应用程序,而数据被添加到窗体对象中。在WPF中,数据是应用程序,而窗体对象只是漂亮的图层,允许用户与数据层进行交互。一旦你习惯了这一点,WPF就会变得更容易 :) - Rachel

12

此外,您可以在menuItem上放置命令...

像这样:

<MenuItem Header="MyContextMenuItem
                  Command="{Binding Path=MyCommand}"
                  CommandTarget="{Binding 
                              RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type DataGrid}}}">

如果您在不同的控件上使用contextMenu,CommandTarget可能非常重要。我经常在这里使用FindAncestor来识别调用者。


1
我使用PlacementTarget来获取调用者。 - Mike

2
以下代码对我有效,InsertQuery/DeleteQuery是在ViewModel中定义的两个ICommand方法。
  <DataGrid.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Insert"
                      Command="{Binding DataContext.InsertQuery, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"/>
            <MenuItem Header="Delete" 
                      Command="{Binding DataContext.DeleteQuery, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"/>
        </ContextMenu>
  </DataGrid.ContextMenu>

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