2010-06-29 131 views
2

通过窗口弹出窗口我的意思是一种弹出窗口,只保留一个窗口/应用程序。据我知道,我必须明确地处理显示/弹出的隐藏基于
Application.Current.Activated /禁用
Application.Current.MainWindow.Activated /禁用
ParentWindow.Activated /禁用

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

我已经为所有这些事件编写了处理程序,并且它们正在杀死我,为什么会出现这样一个令人恼怒的问题。必须有一个简单的方法来处理这个问题。有任何想法吗?WPF创建窗口弹出菜单

回答

1

单个事件处理函数应该可以满足整个作业。

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

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

马克所有Windows需要特殊的行为:

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

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

  • “HideWhenAppInactive”是一个bool att用于标记Windows和弹出窗口的属性属性。它还保留了具有此属性集的所有弹出窗口的记录。
  • “AttachHandler”是一个bool附属属性,附有一个PropertyChangedCallback,该属性附加处理程序。
  • “更新”是更新Windows和弹出窗口的基础上是否有一个明显的&活动窗口中的可见度的方法

这将是这个样子:

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时,没有添加任何代码来分离处理程序,因为为此目的,它们将永远不会以这种方式使用。

+1

我想你的代码,但它有这些问题:通过单击任务栏上的不调用更新 1.最小化/最大化 - 我加StateChanged事件这个 2.在更新你改变窗口的知名度,我需要更改窗口上的弹出窗口的可见性(IsOpen属性)。 – 2010-06-30 11:47:53

+0

由于您已经记录了IsOpen的以前状态,因此处理Popup.IsOpen会更节约。我添加了代码来执行此操作,并添加了StateChanged处理程序。 – 2010-06-30 17:06:10

+0

好吧......就像我说过的,我可以通过处理所有这些事件来实现它,我希望能够直接解决这个问题..我确信有很多人需要这个功能。 – 2010-07-07 16:30:38