WPF Popup ZOrder

时间秒杀一切 提交于 2019-12-09 22:58:26

问题


I am using a WPF Popup, but it popups up above every single window on my desktop, even when my application is minimized. How can I make it stay only on the window it originated? The same thing happens when my window is behind other windows: the popup displays above them all.

"There must be something can be done!"

Thanks.


回答1:


I've tried to solve this issue as well, and have found no good solution. This seems to be the way it is supposed to work, and you can't override that.

The only solution I've come up with is to just use a regular layout panel and raise it's Z-Index, so it is the top-level control (this sort of simulates the Popup). The only time I have found that this won't work is when you have WinForms on the screen through WindowsFormsHosts. Those Winforms are always at a higher Z-Index than any of the WPF stuff. That is when you have to use a Popup to get around it.




回答2:


So I dug through the framework source code to see where it actually causes the window to be topmost and it does this in a private nested class. However, it does not provide an option to either just be a child popup of the main window or to be the topmost window. Here is a hack to make it always a child popup window. One could easily add a dependency property and do some more magic to make it the top most.

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);
            }
        }
    }
}



回答3:


Check this: http://chriscavanagh.wordpress.com/2008/08/13/non-topmost-wpf-popup/

may be this can help you!!




回答4:


Although I've not tried to do it, I've also read that this can be done using adorners...Matt Galbraith suggested it on the MSDN forum when asked the same question...in case anyone is still reading this thread.




回答5:


That's how I solved it:

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


来源:https://stackoverflow.com/questions/1267349/wpf-popup-zorder

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!