打开时获取子菜单弹出窗口?

时间:2018-01-24 13:33:28

标签: wpf

我的xaml中有一棵MenuItem树,我需要在打开一个新关卡时抓住单独的可视树。我正在订阅活动MenuItem.SubmenuOpenedEvent,但这只会给我一个已点击的特定MenuItem的引用。我还需要引用新的可视化树根。有什么建议吗?

在应用程序中的任何位置创建新视觉树时,任何获取新视觉树的方法都会很棒。

我尝试过提取各种私有成员,例如MenuItem._submenuPopupApplication.NonAppWindowsInternal,但结果都是空/空。那里没有运气。

1 个答案:

答案 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;
    }
}