2010-06-29 5 views
2

В окне всплывающего окна я имею в виду всплывающее окно, которое остается только с окном/приложением. Насколько я знаю, что придется явно обрабатывать показа/скрытия всплывающего окна на основе
Application.Current.Activated/деактивируется
Application.Current.MainWindow.Activated/ММГ
ParentWindow.Activated/ММГ

I хотите, чтобы Alt-Tab скрывал/показывал всплывающее окно, всплывающее окно win-D, переключение между окнами в одном приложении ничего не должно делать, восстановление/максимизация с панели задач должна отображаться всплывающим окном.

Я написал обработчиков для всех этих событий, и они убивают меня, почему это такая раздражающая проблема. Должен быть простой способ справиться с этим. Есть идеи?WPF, создающий окно-всплывающее окно

ответ

1

Для всей работы должен быть достаточно одного обработчика событий.

Сначала в вашем App.xaml добавить стиль окна, который устанавливает обработчик события, используя вложенное свойство:

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

Отметить все окна, которые требуют особого поведения:

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

сейчас вам просто нужно создать прикрепленные свойства и метод обновления

  • «HideWhenAppInactive» - это bool att которое используется для обозначения Windows и всплывающих окон. Он также сохраняет запись всех всплывающих окон с этим набором свойств.
  • «AttachHandler» - это свойство, прикрепленное bool, с PropertyChangedCallback, которое прикрепляет обработчик.
  • «Update» является методом, который обновляет видимость Windows, и Popups, основываясь на том, существует ли Видимое & активного окна

Это будет выглядеть примерно так:

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) всплывающего окна в окне. –

+0

Работа с Popup.IsOpen сложнее, так как вы записываете предыдущее состояние IsOpen. Я добавил код для этого, а также обработчик StateChanged. –

+0

Ну ... как я сказал, я могу заставить его работать, обрабатывая все эти события, я надеялся получить прямое решение этой проблемы. Я уверен, что есть много людей, которым нужна эта функциональность. –

Смежные вопросы