WPF Popup ZOrder

时间:2009-08-12 16:45:20

标签: c# wpf xaml z-order

我正在使用WPF Popup,但它会弹出桌面上的每个窗口,即使我的应用程序已最小化。我怎样才能让它只停留在它起源的窗口上?当我的窗口在其他窗口后面时,会发生同样的事情:弹出窗口显示在它们之上。

“必须有一些事情可以做!”

感谢。

5 个答案:

答案 0 :(得分:7)

所以我挖掘了框架源代码,看看它实际上导致窗口最顶端的位置,并在私有嵌套类中执行此操作。但是,它不提供仅作为主窗口的子弹出窗口或作为最顶层窗口的选项。这是一个让它永远成为子弹出窗口的黑客。人们可以很容易地添加一个依赖属性,并做一些神奇的事情来使它成为最重要的。

using System;
using System.Reflection;
using System.Windows;
using System.Windows.Controls.Primitives;

namespace UI.Extensions.Wpf.Controls
{
    public class ChildPopup : Popup
    {
        static ChildPopup()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ChildPopup), new FrameworkPropertyMetadata(typeof(ChildPopup)));
        }

        public ChildPopup()
        {
            Type baseType = this.GetType().BaseType;
            dynamic popupSecHelper = GetHiddenField(this, baseType, "_secHelper");
            SetHiddenField(popupSecHelper, "_isChildPopupInitialized", true);
            SetHiddenField(popupSecHelper, "_isChildPopup", true);
        }

        protected dynamic GetHiddenField(object container, string fieldName)
        {
            return GetHiddenField(container, container.GetType(), fieldName);
        }

        protected dynamic GetHiddenField(object container, Type containerType, string fieldName)
        {
            dynamic retVal = null;
            FieldInfo fieldInfo = containerType.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
            if (fieldInfo != null)
            {
                retVal = fieldInfo.GetValue(container);
            }
            return retVal;
        }

        protected void SetHiddenField(object container, string fieldName, object value)
        {
            SetHiddenField(container, container.GetType(), fieldName, value);
        }

        protected void SetHiddenField(object container, Type containerType, string fieldName, object value)
        {
            FieldInfo fieldInfo = containerType.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
            if (fieldInfo != null)
            {
                fieldInfo.SetValue(container, value);
            }
        }
    }
}

答案 1 :(得分:3)

我也试图解决这个问题,但没有找到好的解决方案。这似乎是它应该工作的方式,你不能覆盖它。

我提出的唯一解决方案是使用常规布局面板并提升它的Z-Index,因此它是顶级控件(这种模拟Popup)。我发现这不起作用的唯一一次是你通过WindowsFormsHosts在屏幕上有WinForms。那些Winforms总是处于比任何WPF更高的Z-Index。那就是你必须使用Popup绕过它。

答案 2 :(得分:1)

答案 3 :(得分:0)

虽然我没有尝试过这样做,但我也读到这可以通过装饰来完成......当被问到同样的问题时,Matt Galbraith在MSDN论坛上提出了这个问题......以防有人还在阅读这个帖子。

答案 4 :(得分:0)

这就是我解决的方法:

    private void Popup_Opened(object sender, EventArgs events)
    {
        Popup popup = (Popup)sender;

        // Get window to make popop follow it when user change window's location.
        Window w = Window.GetWindow(popup);
        // Popups are always on top, so when another window gets focus, we
        // need to close all popups.
        w.Deactivated += delegate (object s, EventArgs e)
        {
            popup.IsOpen = false;
        };
        // When our dialog gets focus again, we show it back.
        w.Activated += delegate (object s, EventArgs e)
        {
            popup.IsOpen = true;
        };
     }