How to access a control through a ContextMenu menu item through a visual tree?

This seems to be a pretty popular topic, but ...

I have the following XAML:

<internal:MyCommandObject x:Name="CommandModel"/> <Button DockPanel.Dock="Bottom" Command="{Binding DoAction, ElementName=CommandModel}"> <Button.ContextMenu> <ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}"> <MenuItem Command="{Binding DoAction, ElementName=CommandModel}"/> </ContextMenu> </Button.ContextMenu> Click Me </Button> 

Now MyCommandObject is a control that provides dynamic commands from a DataContext . You know what will happen next. :)

Basically, the button command works just fine - when I click on it, the DoAction command on MyCommandObject runs fine. However, the command in menuitem is not executed. I tried various tricks, such as setting the DataContext context menu as placementTarget so that it can cross the visual tree of controls, etc., but did nothing.

What specific alignment of the RelativeSource and CommandTarget runes CommandTarget I need for this to work?

+6
source share
1 answer

This is because the DataContext="{Binding PlacementTarget,... binding would set the button as MenuItems DataContext , but that would not add ContextMenu to the VisualTree of your window and that the ElementName would not work. A simple workaround for using ElementName bindings is to add this in window code / UserControl:

 NameScope.SetNameScope(contextMenuName, NameScope.GetNameScope(this)); 

Another solution is to do it -

 <ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}"> <MenuItem Command="{Binding DataContext.DoAction}"/> </ContextMenu> 

DataContext="{Binding PlacementTarget,... set the Button (Placementtarget) as the DataContext of your ContextMenu, so you can use the Button DataContext to bind the command.

Update:

You can try to use NameScope.NameScope Attached Property to set NameScope to XAML, but I'm not sure how you get NameScope parent window without code!

You will need to do something similar to Josh Smith's next article, it provides a way to do this in XAML; but this also includes code (moreover, that one line of code) -

Enable ElementName bindings with ElementSpy

Any specific reason not to use this single line of code?

+4
source

Source: https://habr.com/ru/post/919693/


All Articles