以编程方式添加一个上下文菜单,其Click处理程序知道右键单击了哪个项

本文关键字:处理 Click 程序 右键 单击 添加 方式 编程 菜单 上下文 一个 | 更新日期: 2023-09-27 18:15:00

我正在动态生成一个树(TreeViewItem),并希望将相同的上下文菜单添加到树中的每个项目。因为所有的上下文菜单将是相同的,我想我可以做一个,并将其应用到每个TreeViewItem。(也许这是个坏主意?)似乎这应该工作,只要Click处理程序可以找出哪个TreeViewItem的上下文菜单被打开。

我试着从这里(获得右键单击对象)和这里(以编程方式添加绑定)结合SO答案,并提出了这个:

ContextMenu carContextMenu;
public MainWindow()
{
    InitializeComponent();
    Initialize();
    ConstructTree();
}
void ConstructTree()
{
    string[] carNames = {"Mustang", "Viper", "Jetta"};
    foreach (string car in carNames)
    {
        TreeViewItem carNode = new TreeViewItem();
        carNode.Header = car;
        carNode.ContextMenu = carContextMenu;
        CarTree.Items.Add(carNode);
    }
}
void Initialize()
{
    carContextMenu= new ContextMenu();
    MenuItem newQuery = new MenuItem();
    newQuery.Header = "Drive car...";
    Binding b = new Binding("Parent");
    b.RelativeSource = RelativeSource.Self;
    newQuery.SetBinding(MenuItem.CommandParameterProperty, b);
    newQuery.Click += NewQuery_Click;
    carContextMenu.Items.Add(newQuery);
}
void NewQuery_Click(object sender, RoutedEventArgs e)
{
    MenuItem mi = sender as MenuItem;
    if (mi != null)
    {
        ContextMenu cm = mi.CommandParameter as ContextMenu; // *****
        if (cm != null)
        {
            TreeViewItem node = cm.PlacementTarget as TreeViewItem;
            if (node != null)
            {
                Console.WriteLine(node.Header); // car name, ideally
            }
        }
    }
}

在运行时,当它到达带有星号的行时,mi.CommandParameter为空,因此它跳过方法的其余部分。我的方法怎么了?老实说,我有点惊讶,右键单击的项不是事件处理程序参数的固有部分,因为您经常想知道单击了什么。当右键单击树项目时,它们并不需要被选中,所以检查这不是一个可靠的方法……另外,这只是一个拙劣的变通方法。

谢谢!

以编程方式添加一个上下文菜单,其Click处理程序知道右键单击了哪个项

很自然地,事实证明我把事情复杂化了,我所关注的链接要么是不正确的,要么是过时的,或者(很可能)我误读了他们的场景的某些部分,有些东西实际上并不适用于我。

我不需要MenuItem本身的任何绑定,只是应该一直关注myMenuItem.Parent.PlacementTarget。工作代码如下:

void Initialize()
{
    carContextMenu= new ContextMenu();
    MenuItem newQuery = new MenuItem();
    newQuery.Header = "Drive car...";
    newQuery.Click += NewQuery_Click;
    carContextMenu.Items.Add(newQuery);
}
void NewQuery_Click(object sender, RoutedEventArgs e)
{
    MenuItem mi = sender as MenuItem;
    if (mi != null)
    {
        ContextMenu cm = mi.Parent as ContextMenu;
        if (cm != null)
        {
            TreeViewItem node = cm.PlacementTarget as TreeViewItem;
            if (node != null)
            {
                Console.WriteLine(node.Header);
            }
        }
    }
}