Setting the CommandTarget of a ContextMenu Item to the “Parent” of the ContextMenu in WPF

If you ever wanted to bind a command target on a context menu item to its “parent” (i.e. the control on which the context menu is shown) you noticed that this approach, using RelativeSource with FindAncestor and AncestorType, doesn’t work, assuming you have a control defined as type MyControlType on which you have the context menu:

<ContextMenu>
<MenuItem Command=”YourCommand
    CommandTarget=”{Binding RelativeSource=
        {RelativeSource
            AncestorType=MyControlType}}
“/>
 </ContextMenu>

Instead you should use the PlacementTarget property of the ContextMenu object that owns the context menu item, because the MyControlType object is NOT in the same visual tree as the current context menu item, and therefore RelativeSource cannot find that “parent”:

<ContextMenu>
<MenuItem Command=”YourCommand
    CommandTarget=”{Binding Path=PlacementTarget,
        RelativeSource={RelativeSource
            AncestorType=ContextMenu}}
“/>
</ContextMenu>

I hope it helps someone.

PS: If you need to find an ancestor of the PlacementTarget object and if you own the code for MyControlType, you could write a property in code to get the visual parent you need.

About Sorin Dolha

My passion is software development, but I also like physics.
This entry was posted in Computers and Internet. Bookmark the permalink.

13 Responses to Setting the CommandTarget of a ContextMenu Item to the “Parent” of the ContextMenu in WPF

  1. Christopher says:

    Thanks! Just what I was looking for!

  2. Abdolhosein says:

    Thanks. It works!

  3. Miky says:

    Thank you very much !!! :DI wasted 2 hours until found your useful post.thanks !

  4. Unknown says:

    thank you!!!

  5. Dracub says:

    Hi, I am trying to write that in c# code like:
    item.CommandTarget = new InputBinding()
    {
    Path = new PropertyPath(“PlacementTarget”),
    RelativeSource = new RelativeSource
    { AncestorType = typeof(ContextMenu)}
    };
    but this didn’t work..
    it says: Cannot convert source type ‘System.Windows.Data.Binding’ to target type ‘System.Windows.IInputElement’
    do you know how to write it in c# code? thanks..

    • Sorin Dolha says:

      Try it like this (note that I didn’t test the code, I just converted XAML to C# 4 “by hand”):
      menuItem.CommandTarget = new Binding("PlacementTarget") { RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(ContextMenu), 1) } };

      • Dracub says:

        thanks for an answer🙂 well I solved it that I put
        menuItem.CommandTarget = this;
        because of what CommandTarget is and the fact that I need the context menu to be shown on the control itself..
        and it’s working..🙂
        funny how easy it was, yet I was constructing that long expression😀

  6. Sorin Dolha says:

    Indeed, in code behind it’s easier to set up menuItem.CommandTarget = this, as you have direct access there to the current control object itself.

  7. Steve Lillis says:

    Hi Sorin,
    I just wanted to say a massive thank you. I have literally trawled the entire internet looking for a solution to this issue. As you can imagine; unless you know what you’re looking for with wpf you can find yourself at a total loss. This code is so simple compared to some solutions, makes sense and is super helpful.

    Thanks🙂

  8. ABC says:

    I have a MainPanel. Which has a menu control and a tab control. I am following mvvm pattern for my application. My tab control’s item source is bound to an observable collection of another view model say View1/ViewModel1. My View1 has one tree control. I need to have some context menu for this tree control. And this tree control’s context menu item command is same as some of the menu items in the MainPanel’s Menu control’s item. Say Copy/paste in context menu and in the main control. i read about relative source. And I tried as

    But this didnot work. Can any one give me some answers??

    Iam getting error ” System.Windows.Data Error: 4 : Cannot find source for binding with reference ‘RelativeSource FindAncestor, AncestorType=’MinuteFrontend.Views.MainPanel’, AncestorLevel=’1”. BindingExpression:Path=DataContext.PasteCmnd; DataItem=null; target element is ‘MenuItem’ (Name=’PasteItem’); target property is ‘Command’ (type ‘ICommand’)”

    • Sorin Dolha says:

      You haven’t posted any code, so it’s difficult to know how you are trying to achieve what you need. Try without AncestorLevel=”1″, tough, let it go through all parents.

Add a reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s