【问题标题】:WPF Popup ZOrderWPF 弹出 ZOrder
【发布时间】:2009-08-12 16:45:19
【问题描述】:

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

“一定有什么可以做的!”

谢谢。

【问题讨论】:

  • 我有同样的问题,无法解决。很难相信这是默认行为,但 MSDN 对此毫无用处。我解决它的方法是在窗口 xaml 中将包含组合框的整个窗口设置为 TopMost=True。这使得整个窗口最顶部不仅仅是我的 ComboBox 的下拉列表(与您的弹出框相同)。

标签: c# wpf xaml z-order


【解决方案1】:

因此,我深入研究了框架源代码,以查看它实际导致窗口位于最顶层的位置,并且它在私有嵌套类中执行此操作。但是,它不提供仅作为主窗口的子弹出窗口或作为最顶层窗口的选项。这是一个使其始终成为子弹出窗口的技巧。可以很容易地添加一个依赖属性并做一些更神奇的事情来使它成为最顶级的。

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

【讨论】:

  • 如果您像我一样需要从 ChildPopup 继承,代码将无法按原样工作。我将 popupSecHelper 行更改为: object popupSecHelper = GetHiddenField(this, typeof(Popup), "_secHelper");另外,我跳过了 DefaultStyleKeyProperty 覆盖,因为它似乎不需要,我不明白为什么它应该这样做。
【解决方案2】:

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

我想出的唯一解决方案是只使用常规布局面板并提高它的 Z-Index,因此它是顶级控件(这种模拟弹出窗口)。我发现这不起作用的唯一一次是当您通过 WindowsFormsHosts 在屏幕上显示 WinForms 时。这些 Winform 的 Z-Index 总是高于任何 WPF 的东西。这就是你必须使用 Popup 来绕过它的时候。

【讨论】:

    【解决方案3】:

    检查这个:http://chriscavanagh.wordpress.com/2008/08/13/non-topmost-wpf-popup/

    也许这对你有帮助!!

    【讨论】:

      【解决方案4】:

      我就是这样解决的:

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

      【讨论】:

      • 在提示警报时,主窗口不会停用,提示消息显示在后面
      【解决方案5】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-29
        相关资源
        最近更新 更多