我的xaml中有一棵MenuItem
树,我需要在打开一个新关卡时抓住单独的可视树。我正在订阅活动MenuItem.SubmenuOpenedEvent
,但这只会给我一个已点击的特定MenuItem
的引用。我还需要引用新的可视化树根。有什么建议吗?
在应用程序中的任何位置创建新视觉树时,任何获取新视觉树的方法都会很棒。
我尝试过提取各种私有成员,例如MenuItem._submenuPopup
和Application.NonAppWindowsInternal
,但结果都是空/空。那里没有运气。
答案 0 :(得分:2)
SubmenuOpenedEvent
有点用词不当,因为在它被引发时,子菜单实际上 已被加载到可视化树中。因此,它实际上并没有以最有意义的意义“打开”。
要在子菜单 打开时收到通知,您可以订阅MenuItem.Loaded
。你可以提前做到这一点,但我可能会在SubmenuOpenedEvent
被提出时按需提供:
private void OnMenuItemSubmenuOpened(object sender, RoutedEventArgs e)
{
var menuItem = (MenuItem)sender;
var anyChild = menuItem.Items.OfType<FrameworkElement>().FirstOrDefault();
if (anyChild != null)
{
var handler = default(RoutedEventHandler);
handler = (o, args) =>
{
anyChild.Loaded -= handler;
var popup = anyChild?.FindPopup();
// Do something with the Popup.
};
anyChild.Loaded += handler;
}
}
FindPopup
是一种实用程序扩展方法,定义如下:
public static class UIHelpers
{
public static Popup FindPopup(this DependencyObject popupDescendant)
{
if (popupDescendant == null)
return null;
var popupRoot = popupDescendant.FindVisualRoot() ??
popupDescendant;
return popupRoot.GetLogicalParent() as Popup;
}
public static DependencyObject FindVisualRoot(this DependencyObject sourceElement)
{
var currentElement = sourceElement;
while (currentElement != null)
{
var parent = currentElement.GetVisualParent();
if (parent == null)
return currentElement;
currentElement = parent;
}
return null;
}
public static DependencyObject GetVisualParent(this DependencyObject sourceElement)
{
if (sourceElement == null)
return null;
if (sourceElement is Visual || sourceElement is Visual3D)
return VisualTreeHelper.GetParent(sourceElement);
var contentElement = sourceElement as ContentElement;
if (contentElement != null)
return ContentOperations.GetParent(contentElement);
return null;
}
public static DependencyObject GetLogicalParent(this DependencyObject sourceElement)
{
if (sourceElement == null)
return null;
var logicalParent = LogicalTreeHelper.GetParent(sourceElement);
if (logicalParent != null)
return logicalParent;
var frameworkElement = sourceElement as FrameworkElement;
if (frameworkElement != null)
return frameworkElement.TemplatedParent;
return (sourceElement as FrameworkContentElement)?.TemplatedParent;
}
}