0
votes

In other questions/answers about putting ContextMenu on TreeView elements I always see a reference to TreeView.ItemTemplate. This is great when you want the same menu for all items, What if I want just one TreeViewItem to have a context menu? I figured that would do it:

    <TreeViewItem>
        <TreeViewItem.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Remove This" Click="RemoveRecorder_Click" 
                    DataContext="{Binding RelativeSource={RelativeSource
                    Mode=FindAncestor,AncestorType=TreeViewItem}}"/>
            </ContextMenu>
        </TreeViewItem.ContextMenu>
    </TreeViewItem>

But when I look at DataContext inside RemoveRecorder_Click, DataContext is null.

    private void RemoveRecorder_Click(object sender, RoutedEventArgs e)
    {
        if ((sender as MenuItem).DataContext is TreeViewItem)
        {
            TreeViewItem tvi = (sender as MenuItem).DataContext as TreeViewItem;
            tvi.Parent.RemoveChild(tvi);
        }
    }
1

1 Answers

0
votes

Traversing the Visual and Logical tree from the MenuItem up seems to show that TreeViewItem and MenuItem are not in the same tree despite what the XAML above appears to suggest.

At least at the time the click event handler is running, the root of both Logical and Visual trees that MenuItem is in is PopupRoot.

This answers my question of why my reference did not work.

In my case I did not need to create the ContextMenu in XAML I was going to create both the Context Menu and the tree node in code anyway. In that case there is no problem, I assign the DataContext directly:

        MenuItem mu = new MenuItem();
        mu.Header = "Remove Node";
        mu.Click += RemoveRecorder_Click;
        mu.DataContext = RemovableNode;
        ContextMenu cu = new ContextMenu();
        cu.Items.Add(mu);
        RemovableNode.ContextMenu = cu;

RemovableNode is :

<TreeViewItem Header="ITEM 1" IsExpanded="False" Name="RemovableNode">