2010-06-29 104 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