通过window-popup我的意思是一个弹出窗口只有一个窗口/应用程序。据我所知,我将必须明确处理基于
Application.Current.Activated / Deactivated显示/隐藏弹出窗口
Application.Current.MainWindow.Activated /禁用
ParentWindow.Activated /禁用
我想确保Alt-Tab隐藏/显示弹出窗口,win-D隐藏弹出窗口,在同一应用程序中的窗口之间切换应该什么都不做,从任务栏恢复/最大化应该显示弹出窗口。
我为所有这些事件编写了处理程序,他们正在杀了我,为什么这是一个令人恼火的问题。必须有一种简单的方法来处理这个问题。有什么想法吗?
答案 0 :(得分:1)
单个事件处理程序应该足以完成整个作业。
首先在App.xaml中添加一个Window样式,使用附加属性设置事件处理程序:
<Style TargetType="Window">
<Setter Property="local:PopupWindowControl.AttachHandler" Value="true" />
</Style>
标记所有需要特殊行为的窗口:
<Window local:PopupWindowControl.HideWhenAppInactive="true" ... >
现在您只需要创建附加属性和更新方法
它看起来像这样:
public class PopupWindowControl : DependencyObject
{
// HideWhenAppInactive
public static bool GetHideWhenAppInactive(DependencyObject obj) { return (bool)obj.GetValue(HideWhenAppInactiveProperty); }
public static void SetHideWhenAppInactive(DependencyObject obj, bool value) { obj.SetValue(HideWhenAppInactiveProperty, value); }
public static readonly DependencyProperty HideWhenAppInactiveProperty = DependencyProperty.RegisterAttached("HideWhenAppInactive", typeof(bool), typeof(PopupWindowControl), new PropertyMetadata
{
PropertyChangedCallback = (obj, e) =>
{
if((bool)e.NewValue && obj is Popup)
{
if((_cleanupCounter++ % 10000) == 0)
_hideWhenInactivePopups = (from weakRef in _hideWhenInactivePopups where weakRef.IsAlive select weakRef).ToList();
_hideWhenInactivePopups.Add(new WeakReference(obj));
}
}
});
// AttachHandler
public static bool GetAttachHandler(DependencyObject obj) { return (bool)obj.GetValue(AttachHandlerProperty); }
public static void SetAttachHandler(DependencyObject obj, bool value) { obj.SetValue(AttachHandlerProperty, value); }
public static readonly DependencyProperty AttachHandlerProperty = DependencyProperty.RegisterAttached("AttachHandler", typeof(bool), typeof(PopupWindowControl), new PropertyMetadata
{
PropertyChangedCallback = (obj, e) =>
{
if((bool)e.NewValue)
{
var window = (Window)obj;
window.Activated += Update;
window.Deactivated += Update;
window.StateChanged += Update;
}
}
});
private static void Update(object sender, EventArgs e)
{
var active =
Application.Current.Windows.OfType<Window>().Where(win =>
win.IsActive &&
win.Visibility==Visibility.Visible &&
win.WindowState != WindowState.Minimized)
.Any();
// First update Windows marked HideWhenAppInactive
foreach(var popupWindow in Application.Current.Windows.OfType<Window>().Where(win => GetHideWhenAppInactive(win)))
popupWindow.Visibility = active ? Visibility.Visible : Visibility.Hidden;
// Then update Popups marked HideWhenAppInactive
if(active && _temporarilyHiddenPopups!=null)
{
foreach(var popup in _temporarilyHiddenPopups)
popup.IsOpen = true;
_temporarilyHiddenPopups = null;
}
else if(!active)
{
if(_temporarilyHiddenPopups==null) _temporarilyHiddenPopups = new List<Popup>();
foreach(var popup in
(from weak in _hideWhenInactivePopups
let popup = weak.Target as Popup
where popup!=null && popup.IsOpen && GetHideWhenAppInactive(popup)
select popup))
{
_temporarilyHiddenPopups.Add(popup);
popup.IsOpen = false;
}
}
}
private static List<WeakReference> _hideWhenInactivePopups = new List<WeakReference>();
private static List<Popup> _temporarilyHiddenPopups;
private static int _cleanupCounter;
}
请注意,当“AttachHandler”或“HideWhenAppInactive”设置为false时,我没有添加任何代码来分离处理程序,因为为此目的,它们永远不会以这种方式使用。