How to access a control from a ContextMenu menuitem via the visual tree?

不想你离开。 提交于 2019-11-26 17:18:30

问题


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 which exposes dynamic commands from its DataContext. You know what's coming next. :)

Basically, the button command works perfectly - when I click it, the DoAction command on the MyCommandObject gets executed perfectly. However, the command in the menuitem doesn't get executed. I've tried various tricks such as setting the context menu datacontext to be the placementTarget so it can traverse the visual tree of the controls and so on, but nothing's doing.

What particular alignment of RelativeSource and CommandTarget runes do I need to get this to work?


回答1:


This is happening because DataContext="{Binding PlacementTarget,... binding would set the button as MenuItems DataContext but that won't add the ContextMenu to the VisualTree of your window and that's why ElementName binding's won't work. A simple workaround to use ElementName bindings is to add this in your Window/UserControl's code-behind:

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

Another solution is to do this -

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

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

Update:

You can try and use the NameScope.NameScope Attached Property to set NameScope in XAML but I am not sure how you will get the NameScope of parent window without code!

You will have to do something similar to following article by Josh Smith, he provides a way to do this in XAML; but that too involves code (more then that single line of code) -

Enable ElementName Bindings with ElementSpy

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



来源:https://stackoverflow.com/questions/11333028/how-to-access-a-control-from-a-contextmenu-menuitem-via-the-visual-tree

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!