32

I have a ContextMenu like this:

<StackPanel Orientation="Horizontal">
    <StackPanel.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Delete" Click="OnDeleteClicked" />
        </ContextMenu>
    </StackPanel.ContextMenu>
</StackPanel>

And I need to get the instance of the StackPanel that owns that ContextMenu. I already tried this:

private void OnDeleteClicked(object sender, System.Windows.RoutedEventArgs e)
{
    FrameworkElement parent = e.OriginalSource as FrameworkElement;

    while (!(parent is StackPanel))
    {               
        parent = (FrameworkElement)LogicalTreeHelper.GetParent(parent);
    }
}

But after getting the ContextMenu Popup parent, it gets null, same with the VisualTreeHelper, it gets to null before getting the StackPanel. Any idea on how to do this?

Thanks!

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
Carlo
  • 25,602
  • 32
  • 128
  • 176

3 Answers3

63

this will give you the exact thing you want

private void OnDeleteClicked(object sender, System.Windows.RoutedEventArgs e)
{
    MenuItem mnu = sender as MenuItem;
    StackPanel sp = null;
    if(mnu!=null)
    {
        sp = ((ContextMenu)mnu.Parent).PlacementTarget as StackPanel;
    }
}

Hope this helps!!

viky
  • 17,275
  • 13
  • 71
  • 90
  • The ContextMenu's PlacementTarget property is only set when Right Clicking on the control containing the ContextMenu. If the parent control isn't right clicked, the ContextMenu's PlacementTarget will be null. – Mort Dec 09 '21 at 11:45
9

The visual tree for ContextMenus and Popups works a little differently. You can use ContextMenu.PlacementTarget to get the StackPanel. There is more information available on MSDN here: http://msdn.microsoft.com/en-us/library/system.windows.controls.contextmenu.placementtarget.aspx

Amanduh
  • 1,233
  • 1
  • 13
  • 23
1

the context menu has its own visual tree, try this calling this from your event handler like so :-

StackPanel stackPanel = GetStackPanelItemFromContextMenu((FrameworkElement)sender, yourStackPanel);

  private StackPanel GetStackPanelItemFromContextMenu(FrameworkElement sender, StackPanel stackPanel) {
     Point menuClickPoint = ((sender as FrameworkElement).Parent as ContextMenu).TranslatePoint(new Point(0, 0), stackPanel);

     // get the first potential object that was hit   
     DependencyObject obj = stackPanel.InputHitTest(menuClickPoint) as DependencyObject;

     // cycle up the tree until you hit the StackPanel
     while (obj != null && !(obj is StackPanel)) {
        obj = VisualTreeHelper.GetParent(obj);
     }

     return obj as StackPanel;
  }
Aran Mulholland
  • 23,555
  • 29
  • 141
  • 228