2010-06-29 18 views
2

Par fenêtre-pop-up, je veux dire un popup qui reste en quelque sorte avec une fenêtre/application. Pour autant que je sais que je vais devoir gérer explicitement montrer/cacher de pop-up basée sur
Application.Current.Activated/Désactivé
Application.Current.MainWindow.Activated/Désactivé
ParentWindow.Activated/Désactivé

I vous voulez vous assurer que Alt-Tab cache/affiche le popup, win-D cache popup, basculer entre les fenêtres de la même application ne devrait rien faire, la restauration/maximisation depuis la barre des tâches devrait afficher popup. J'ai des gestionnaires écrits pour tous ces événements, et ils me tuent, pourquoi est-ce un problème si irritant. Il doit y avoir un moyen simple de gérer cela. Des idées?WPF la création de fenêtre-popup

Répondre

1

Un gestionnaire d'événement unique devrait suffire pour l'ensemble du travail.

d'abord dans votre App.xaml ajouter un style de fenêtre qui définit le gestionnaire d'événements en utilisant une propriété attachée:

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

Mark toutes vos fenêtres qui ont besoin du comportement spécial:

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

maintenant vous avez juste besoin de créer les propriétés attachées et une méthode de mise à jour

  • "HideWhenAppInactive" est un bool att propriété douloureuse utilisée pour marquer Windows et Popups. Il maintient également un enregistrement de tous les Popups avec cet ensemble de propriétés. "AttachHandler" est une propriété jointe à un booléen avec un PropertyChangedCallback qui attache le gestionnaire.
  • « Mise à jour » est une méthode qui met à jour la visibilité de Windows et popups basée sur l'existence d'une & visible fenêtre active

Il ressemblerait à quelque chose comme ceci:

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; 
} 

Notez que je n'a pas ajouté de code pour détacher le gestionnaire lorsque "AttachHandler" ou "HideWhenAppInactive" sont définis sur false car, à cette fin, ils ne seront jamais utilisés de cette façon.

+1

J'ai essayé votre code, mais il a ces questions: 1. cacher/en cliquant sur Taskbar n'invoque pas mise à jour - j'ajouté événement StateChanged pour cette 2. Dans la mise à jour vous changez la visibilité de la fenêtre, je besoin de changer la visibilité (propriété IsOpen) de popup sur une fenêtre. –

+0

Traiter avec Popup.IsOpen est un jeu d'enfant puisque vous avez enregistré l'état précédent de IsOpen. J'ai ajouté le code pour le faire, ainsi que le gestionnaire StateChanged. –

+0

Eh bien ... comme je l'ai dit je peux le faire fonctionner en manipulant tous ces événements, j'espérais obtenir une solution simple à ce problème .. Je suis sûr qu'il y a beaucoup de gens qui ont besoin de cette fonctionnalité. –

Questions connexes