WPF的ContextMenu没有类似WinForm里面ContextMenu.SourceControl的概念,但是你可以通过ContextMenuService的GetPlacementTarget方法来获取类似的效果。
很多时候,我们会希望在WPF的资源文件里面定义一个通用的右键弹出菜单,然后将这个菜单通过定义在各个控件的ContextMenu属性来设置用户右击控件时弹出菜单。然而因为WPF的一些设计不足,你不能在右键菜单的点击事件处理函数中获知右键菜单弹出时,鼠标的焦点是在哪个控件上?
例如下面的代码:
XAML代码:
<Window.Resources>
<ContextMenux:Key="sampleContextMenu">
<MenuItemHeader="MenuItem1"Click="WhoBringMeOut"/>
ContextMenu>
...
Window.Resources>
<TreeView>
<TreeViewItemHeader="TreeViewItem1"ContextMenu="{StaticResource
sampleContextMenu}"/>
<TreeViewItemHeader="TreeViewItem2"ContextMenu="{StaticResource
sampleContextMenu}"/>
<TreeViewItemHeader="TreeViewItem3"/>
TreeView>
<DockPanelContextMenu="{StaticResource
sampleContextMenu}">
<ImageSource="img1.ico"/>
<TextBlockText="QuicklyAccess"/>
DockPanel>
C#代码:
public void WhoBringMeOut(object sender,
RoutedEventArgs e)
{
//
sender的值是被点击的MenuItem,而不是触发右键菜单
//弹出的控件,例如TreeViewItem,或者是DockPanel
}
这种情况下你可以通过ContextMenuService的GetPlacementTarget方法来获取类似的效果。
然而,看起来WPF在MenuItem.Click事件处理上面有一点bug,就是你不能通过(sender as
MenuItem).ContextMenu
获取到点击的右键菜单,只好求助于LogicalTreeHelper.GetParent方法了,
使用下面的方法获取到ContextMenu的Owner: ContextMenuService.GetPlacementTarget(LogicalTreeHelper.GetParent(sender
as MenuItem))
也就是说上面的C#代码改成下面的样子就可以了:
public void WhoBringMeOut(object sender,
RoutedEventArgs e)
{
ContextMenuService.GetPlacementTarget(
LogicalTreeHelper.GetParent(sender as MenuItem));
}