我正在使用 WPF 弹出窗口,但即使我的应用程序已最小化,它也会在我桌面上的每个窗口上方弹出。我怎样才能让它只停留在它起源的窗口上?当我的窗口位于其他窗口之后时也会发生同样的事情:弹出窗口显示在所有窗口之上。
“一定有什么可以做的!”
谢谢。
因此,我挖掘了框架源代码以查看它实际导致窗口位于最顶层的位置,并且它在私有嵌套类中执行此操作。但是,它不提供仅作为主窗口的子弹出窗口或作为最顶层窗口的选项。这是一个使其始终成为子弹出窗口的技巧。人们可以轻松地添加一个依赖属性并做一些更神奇的事情来使它成为最顶级的。
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);
}
}
}
}
我也尝试过解决这个问题,但没有找到好的解决方案。这似乎是它应该工作的方式,你不能覆盖它。
我想出的唯一解决方案是只使用常规布局面板并提高它的 Z-Index,因此它是顶级控件(这种模拟弹出窗口)。我发现这不起作用的唯一一次是当您通过 WindowsFormsHosts 在屏幕上显示 WinForms 时。这些 Winform 的 Z-Index 总是高于任何 WPF 的东西。那是您必须使用弹出窗口来绕过它的时候。
我就是这样解决的:
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;
};
}
虽然我没有尝试这样做,但我也读到这可以使用装饰器来完成......当被问到同样的问题时,Matt Galbraith 在 MSDN 论坛上提出了它......以防有人仍在阅读这个线程。