Pregunta La aplicación WPF pierde completamente el foco en el cierre de la ventana


Descripción del problema

Si configuro una ventana no modal como una ventana secundaria configurando el propietario de la ventana en una ventana primaria y luego mostrando un cuadro de mensaje desde esta ventana secundaria, la ventana principal perderá el foco si cierro la ventana secundaria. Si Windows Explorer u otra aplicación está abierta, esta aplicación obtendrá el foco y mi ventana principal estará oculta.

Esto parece ser un problema conocido ya que lo vi en otro grupos de noticias, pero no he visto una buena solución. Establecer al propietario como nulo en OnDeactivate no es una opción. Configurar el propietario antes de mostrar MessageBox para anular y restablecer después de eso no ayuda. Establecer que el propietario anule en el evento OnClosed tampoco ayuda.

Solución simple encontrada

Si experimenta el mismo problema que he descrito, coloque el siguiente código en el Encierro de todas las ventanas secundarias.

void  OnClosing(System.ComponentModel.CancelEventArgs e)
  base.OnClosing(e);
  if (null != Owner) {
         Owner.Activate();
  }
  // ....

Puede ser seguido por cualquier lógica de procesamiento adicional, incluso se tolera la apertura de MessageBoxes.

Código de ejemplo

El problema parece ser mucho más grande, como yo pensaba. El siguiente ejemplo eliminará el foco de la ventana principal si se abrirá el cuadro de mensaje y se cerrará la ventana secundaria (Copie el código en un controlador de eventos cargado de una Ventana).

Window firstChildWindow = new Window() {
    Title = "Floating Window", Width = 100, Height = 70
};
firstChildWindow.Owner = Window.GetWindow(this);

Button button = new Button() { Content="MessageBox"};
button.Click += delegate { 
    MessageBox.Show("Klicking her breaks the focus-chain."); };
firstChildWindow.Content = button;
firstChildWindow.Show();

También este ejemplo rompe la cadena de enfoque:

Window firstChildWindow = new Window() {
    Title = "Floating Window", Width = 100, Height = 70
};
firstChildWindow.Owner = Window.GetWindow(this);
firstChildWindow.Show();

Window secondChildWindow = new Window() { 
    Title="Second Window",Width=100,Height=70};
secondChildWindow.Content = new TextBlock() { 
    Text="SecondWindow"};
secondChildWindow.Owner = firstChildWindow;
secondChildWindow.Show();

Alguien tiene una resolución para este problema. Pienso en un truco para desencadenar dando enfoque al padre después del cierre, con Dispatcher o DispachterTimer o quizás sería trabajo forzar manualmente el enfoque al padre en el cerrado, pero todo esto me parece muy sucio (y también es un poco complicado si hay ventanas de propiedad más activa del mismo padre, como tengo en mi aplicación actual).

Nadie sabe una solución clara para esto?

Recursos

Descripción de MSDN (ver abajo comentarios para ventanas no modales abiertas llamando a Show ())

El mismo problema en los foros msdn sin la solución adecuada

Por favor vea también: Enfoque instable de las aplicaciones WPF


32
2018-06-29 21:02


origen


Respuestas:


Lo más probable es que haya dos ventanas de nivel superior independientes y haya cerrado una de ellas. Esto a veces provocará que el foco salte a otra aplicación.

Esto también ocurre si un windows posee un segundo, que a su vez posee un tercero. Probable ERROR en la API de Win32 pero ha estado con nosotros para siempre, así que buena suerte para solucionarlo.

La solución consiste en volver a centrar manualmente la mano en el evento Closing del nieto. Pero en este caso, nieto es un mensaje para que no puedas hacer eso. Lo más fácil de hacer es tener un messagebox para parent. El siguiente más fácil es hacer su propio control de cuadro de mensaje.


22



Este es un error muy molesto, la solución más común es:

llamada Me.Owner.Focus en el Window_Unloaded o Window_Closing evento.

Pero eso aún no funciona al 100%, aún se ve la ventana de fondo parpadeando en primer plano (muy brevemente), antes de que el foco se restaure correctamente.

Encontré un método que funciona mejor:

llamada Me.Owner.Activateantes de Me.Close (o en el _Closing evento).


20



Tal vez estoy bastante tarde en el asunto.
@HCL este problema podría resolverse más fácilmente configurando opciones parámetro de la MessageBox.show () a MessageBoxOptions.None.

Aclamaciones...


2



es posible escribir su propio cuadro de mensaje, puede implementarlo como un flotador, deshabilitar toda la pantalla cuando se muestre.

usted revisa la muestra calibwar mvvm frameork, hay una buena implementación de messagebox como servicio.


0



La propiedad no tiene nada que ver con la activación de la ventana. Para ver esto, cambie el propietario de la segunda ventana a la ventana superior y ejecute el programa. Observe que nada cambia. La propiedad tiene que ver con "Si se minimiza una ventana, se deben minimizar otras ventanas". Por lo tanto, tiene que usar el código de activación personalizado.


0



La solución .Activate (ver arriba) de Johsua funciona bastante bien con todo tipo de tipos de ventanas. Al menos me hizo el truco.


0



Tuve un problema similar. Tenía una ventana principal, donde las ventanas secundarias restantes se asignaban a esa ventana a través de la propiedad Propietario. Si la ventana principal tenía dos o más hijos, después de cerrar el segundo hijo, la aplicación pierde el foco. Usé truco con child.Owner = null antes de cerrar, pero luego mi ventana secundaria siguiente pierde el foco. Lo manejé al obtener todos los hijos y establecer el foco en el último antes de cerrar al niño. Aquí está el ejemplo del código:

private void OnClosing(object sender, CancelEventArgs cancelEventArgs)
        {
            var childWindows = (sender as Window).Owner.OwnedWindows;
            if (childWindows.Count - 2 >= 0)
                childWindows[childWindows.Count - 2].Focus();
            else
            {
                (sender as Window).Owner.Focus();
            }
            (sender as Window).Owner = null;
        }

0