这个框架实际上是在PopupControlService.所有者属性,但它是一个内部类。如果您愿意使用未记录的功能,可以迭代上下文菜单上的属性并将其拉出:
private static object GetOwner(ContextMenu menu)
{
var prop = menu.GetLocalValueEnumerator();
while (prop.MoveNext())
{
if (prop.Current.Property.Name == "Owner" &&
prop.Current.Property.OwnerType.Name == "PopupControlService")
{
return prop.Current.Value;
}
}
return null;
}
ContextMenuService.ContextMenuOpeningEvent
public class ContextMenuOwnerTracker
{
private static bool isInitialized;
public static void Initialize()
{
if (!isInitialized)
{
isInitialized = true;
EventManager.RegisterClassHandler(typeof(ContentElement),
ContextMenuService.ContextMenuOpeningEvent,
new ContextMenuEventHandler(OnContextMenuOpening));
EventManager.RegisterClassHandler(typeof(ContentElement),
ContextMenuService.ContextMenuClosingEvent,
new ContextMenuEventHandler(OnContextMenuClosing));
}
}
private static void OnContextMenuOpening
(object sender, ContextMenuEventArgs args)
{
var menu = ContextMenuService.GetContextMenu((DependencyObject)sender);
if (menu != null)
{
SetOwner(menu, sender);
}
}
private static void OnContextMenuClosing
(object sender, ContextMenuEventArgs args)
{
var menu = ContextMenuService.GetContextMenu((DependencyObject)sender);
if (menu != null)
{
ClearOwner(menu);
}
}
private static readonly DependencyPropertyKey OwnerKey =
DependencyProperty.RegisterAttachedReadOnly(
"Owner",
typeof(object),
typeof(ContextMenuOwnerTracker),
new PropertyMetadata(null));
public static readonly DependencyProperty OwnerProperty =
OwnerKey.DependencyProperty;
public static object GetOwner(ContextMenu element)
{
return element.GetValue(OwnerProperty);
}
private static void SetOwner(ContextMenu element, object value)
{
element.SetValue(OwnerKey, value);
}
private static void ClearOwner(ContextMenu element)
{
element.ClearValue(OwnerKey);
}
}
请注意,可能有多个ContentElements具有ContextMenu属性,这实际上会为所有这些属性设置所有者,即使这只对实际显示的一个有影响。
要获取特定MenuItem的值,必须遍历树或使用绑定
{RelativeSource AncestorType=ContextMenu}
. 您还可以标记继承的所有者属性,使其自动传播到MenuItems。
如果您将上下文菜单附加到比超链接更高的级别,则可以使用OriginalSource而不是sender,但这通常会给您一个运行时间,因此您必须在树上查找超链接。