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

时间:2016-10-26 17:48:36

标签: c# .net wpf

我动态生成树(TreeViewItem s),并希望将相同的上下文菜单添加到树中的每个项目。因为所有上下文菜单都是相同的,所以我想我可以制作一个,并将其应用于每个TreeViewItem。 (也许这是一个坏主意?)只要Click处理程序可以找出打开了TreeViewItem的上下文菜单,这样看起来应该可行。

我尝试将来自here(获取右键单击的对象)和here(以编程方式添加绑定)的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为空,因此它会跳过该方法的其余部分。我的做法有什么变化?老实说,我有点惊讶的是,右键单击的项目不是事件处理程序参数的固有部分,因为您经常想知道点击的内容。在右键单击树项目时,不必选择树项目,因此检查这不是一个可靠的方法......加上它只是一个hacky解决方法。

谢谢!

1 个答案:

答案 0 :(得分:0)

当然,事实证明我过于复杂的事情和我所关注的链接要么是不正确的,过时的,要么(很可能)我误读了他们场景的某些部分并且有些东西实际上没有适用对我来说。

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);
            }
        }
    }
}