Wpf 创建窗口弹出窗口

Wpf 创建窗口弹出窗口,wpf,popup,Wpf,Popup,所谓窗口弹出,我指的是一种仅停留在窗口/应用程序中的弹出。据我所知,我必须根据Application.Current.Activated/Deactivated明确处理弹出窗口的显示/隐藏 Application.Current.MainWindow.Activated/Deactivated ParentWindow.Activated/Deactivated 我想确保Alt Tab隐藏/显示弹出窗口,win-D隐藏弹出窗口,在同一应用程序中的窗口之间切换应该什么都不做,从任务栏恢复/最大

所谓窗口弹出,我指的是一种仅停留在窗口/应用程序中的弹出。据我所知,我必须根据
Application.Current.Activated/Deactivated明确处理弹出窗口的显示/隐藏
Application.Current.MainWindow.Activated/Deactivated
ParentWindow.Activated/Deactivated

我想确保Alt Tab隐藏/显示弹出窗口,win-D隐藏弹出窗口,在同一应用程序中的窗口之间切换应该什么都不做,从任务栏恢复/最大化应该显示弹出窗口。


我已经为所有这些事件编写了处理程序,它们正在杀死我,为什么这是一个如此令人恼火的问题。必须有一个简单的方法来处理这个问题。有什么想法吗?

单个事件处理程序应该足以完成整个作业

首先,在App.xaml中添加一个使用附加属性设置事件处理程序的窗口样式:

<Style TargetType="Window">
  <Setter Property="local:PopupWindowControl.AttachHandler" Value="true" />
</Style>

标记所有需要特殊行为的窗口:

<Window local:PopupWindowControl.HideWhenAppInactive="true" ... >

现在您只需要创建附加的属性和更新方法

  • “HideWhenAppInactive”是一个bool附加属性,用于标记窗口和弹出窗口。它还维护具有此属性集的所有弹出窗口的记录
  • “AttachHandler”是一个bool附加属性,带有附加处理程序的PropertyChangedCallback
  • “更新”是一种根据是否存在可见和活动窗口来更新窗口和弹出窗口可见性的方法
它看起来像这样:

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;
}
公共类PopupWindowControl:DependencyObject
{
//躲藏
公共静态bool GetHideWhenAppInactive(DependencyObject对象){return(bool)obj.GetValue(HideWhenAppInactiveProperty);}
公共静态无效SetHideWhenAppInactive(DependencyObject对象,布尔值){obj.SetValue(HideWhenAppInactiveProperty,值);}
public static readonly DependencyProperty HideWhenAppInactiveProperty=DependencyProperty.RegisterAttached(“HideWhenAppInactive”)、typeof(bool)、typeof(PopupWindowControl)、new PropertyMetadata
{
PropertyChangedCallback=(对象,e)=>
{
如果((bool)e.NewValue&&obj弹出)
{
如果(_cleanupCounter++%10000)==0)
_hideWhenInactivePopups=(从weakRef.IsAlive所在的weakRef hideWhenInactivePopups选择weakRef.ToList();
_添加(新的WeakReference(obj));
}
}
});
//AttachHandler
公共静态bool GetAttachHandler(DependencyObject对象){return(bool)obj.GetValue(AttachHandlerProperty);}
公共静态void SetAttachHandler(DependencyObject对象,bool值){obj.SetValue(AttachHandlerProperty,value);}
public static readonly DependencyProperty AttachHandlerProperty=DependencyProperty.RegisterAttached(“AttachHandler”、typeof(bool)、typeof(PopupIndowControl)、new PropertyMetadata
{
PropertyChangedCallback=(对象,e)=>
{
if((bool)e.NewValue)
{
变量窗口=(窗口)对象;
window.Activated+=更新;
window.Deactivated+=更新;
window.StateChanged+=更新;
}
}
});
私有静态无效更新(对象发送方、事件参数)
{
无功有效=
Application.Current.Windows.OfType()。其中(win=>
赢&&
win.Visibility==Visibility.Visible&&
win.WindowState!=WindowState.Minimized)
.Any();
//第一次更新标记为HideWhenAppInactive的窗口
foreach(Application.Current.Windows.OfType()中的var popupWindow.Where(win=>gethidewhenapinactive(win)))
popupWindow.Visibility=活动?可见性。可见:可见性。隐藏;
//然后更新标记为HideWhenAppInactive的弹出窗口
if(活动和临时隐藏弹出窗口!=null)
{
foreach(临时隐藏的弹出窗口中的var弹出窗口)
popup.IsOpen=true;
_临时HiddenPups=null;
}
否则,如果(!活动)
{
如果(_temporaryHiddenPups==null)_temporaryHiddenPops=new List();
foreach(var)在
(在活动弹出窗口时从弱隐藏)
让popup=弱。目标为popup
其中popup!=null&&popup.IsOpen&&gethidewhenapinactive(popup)
选择“弹出窗口”)
{
_临时隐藏弹出窗口。添加(弹出窗口);
popup.IsOpen=false;
}
}
}
私有静态列表_hidewheinactivepopups=new List();
私有静态列表\u临时隐藏的弹出窗口;
专用静态int_清除计数器;
}

请注意,当“AttachHandler”或“HideWhenAppInactive”设置为false时,我没有添加任何代码来分离处理程序,因为出于此目的,它们永远不会以这种方式使用。

我尝试了您的代码,但它有以下问题:1。通过单击任务栏最小化/最大化不调用更新-我为此2添加了StateChanged事件。在更新中,您正在更改窗口的可见性,我需要更改窗口上弹出窗口的可见性(IsOpen属性)。处理popup.IsOpen是个难题,因为您已经记录了IsOpen的以前状态。我添加了执行此操作的代码,以及StateChanged处理程序。。。就像我说的,我可以通过处理所有这些事件来让它工作,我希望得到一个简单的解决方案来解决这个问题。。我确信有很多人需要这个功能。