c# - studio - La aplicación WPF no se apaga al cerrar la ventana principal
visual studio wpf (5)
Estoy acostumbrado a la programación de WinForms en Visual Studio, pero quería darle una oportunidad a WPF.
Agregué otra ventana a mi proyecto, llamada Window01. La ventana principal se llama MainWindow. Antes del constructor public MainWindow()
declaro Window01:
Window01 w1;
Ahora instanciar esta ventana en:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
w1 = new Window01();
}
Tengo un botón donde se muestra la ventana: w1.ShowDialog();
.
Lo ''curioso'' aquí es el hecho de que si comienzo la aplicación (con depuración) y la salgo unos segundos después (no hago nada en la aplicación), Visual Studio no detiene la depuración como si la aplicación estuviera Aún corriendo.
Si muevo la línea w1 = new Window01();
al método de clic de botón, lo que significa que justo encima de ShowDialog()
, Visual Studio se comporta correctamente, es decir, la depuración se detiene cuando salgo de la aplicación.
¿Por qué este extraño comportamiento?
En su MainWindow.xaml.cs
, intente hacer esto:
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
Application.Current.Shutdown();
}
Según este enlace, también puede configurar ShutdownMode
en XAML:
http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
ShutdownMode="OnExplicitShutdown"
>
</Application>
Las aplicaciones dejan de ejecutarse solo cuando se llama al método de Shutdown
de la Application
. El apagado puede ocurrir implícita o explícitamente, según lo especificado por el valor de la propiedad ShutdownMode
.
Si configura ShutdownMode
en OnLastWindowClose
, Windows Presentation Foundation (WPF) llama implícitamente a Shutdown cuando se cierra la última ventana de una aplicación, incluso si las ventanas actualmente creadas se configuran como la ventana principal (consulte MainWindow).
Un ShutdownMode
de OnMainWindowClose
hace que WPF llame implícitamente a Shutdown cuando se cierra MainWindow, incluso si otras ventanas están actualmente abiertas.
La duración de algunas aplicaciones puede no depender de cuándo se cierra la ventana principal o la última ventana, o puede no depender en absoluto de Windows. Para estos escenarios, debe establecer la propiedad ShutdownMode
en OnExplicitShutdown
, que requiere una llamada explícita al método de Shutdown
para detener la aplicación. De lo contrario, la aplicación continúa ejecutándose en segundo plano.
ShutdownMode
se puede configurar declarativamente desde XAML o programáticamente desde el código.
Esta propiedad solo está disponible desde el hilo que creó el objeto Application
.
En su caso, la aplicación no se cierra porque probablemente esté utilizando el valor predeterminado OnLastWindowClose
:
Si configura ShutdownMode
en OnLastWindowClose
, WPF llama implícitamente a Shutdown cuando se cierra la última ventana de una aplicación, incluso si las ventanas actualmente creadas se configuran como la ventana principal (consulte MainWindow
).
Como abres una nueva ventana y no la cierras, no se llama a shutdown.
Me alegro de que hayas recibido tu respuesta, pero por el bien de otros responderé a tu pregunta como ... bueno, para agregar algo de información.
Paso 1
Primero, si desea que su programa salga cuando la ventana principal se cierra, debe especificar, ya que esto no es WinForms donde este comportamiento es el predeterminado.
(El valor predeterminado en WPF es cuando la última ventana se cierra)
En codigo
Vaya a la instancia de su aplicación en su punto de entrada (En el programa WPF de VS 2012, el valor predeterminado está anidado dentro de App.xaml
, así que entre en él y navegue a App.xaml.cs
y cree un constructor).
En el constructor, especifique que http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx su Application
debe ser ShutdownMode
. OnLastWindowClose
.
public App()
{
ShutdownMode = ShutdownMode.OnLastWindowClose;
}
En XAML
Vaya a su archivo App.xaml
que VS 2012 creó de forma predeterminada (o App.xaml
usted mismo). La raíz es una Application
, especifique en su interior que el Application
de http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx debe ser ShutdownMode
. OnLastWindowClose
.
<Application x:Class="WpfApplication27.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
ShutdownMode="OnMainWindowClose">
Si funciona, ya terminaste; puedes dejar de leer
Paso 2
Si lo anterior no funcionó (supongo que escribió la aplicación WPF desde cero), la aplicación probablemente no conozca la ventana principal como la ventana principal. Entonces especifique eso como ... bueno.
En codigo
Vaya al constructor de la aplicación como lo hizo en el Paso 1 y especifique esa Application
. El valor de MainWindow
es su Window
:
MainWindow = mainWindow;
En XAML
Vaya a la Application
XAML como lo hizo en el Paso 1 y especifique esa Application
. El valor de MainWindow
es su Window
:
MainWindow = "mainWindow";
Alternativa
No creo que este sea el mejor enfoque, solo porque WPF no quiere que hagas esto (por lo que tiene el Application
de http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx ), pero puedes usar un evento / reemplazar un método de evento (OnEventHappened).
Vaya al archivo de código subyacente de MainWindow y agregue:
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
App.Current.Shutdown();
}
Me topé con esta pregunta cuando buscaba otra cosa y me sorprendió que no pudiera ver ninguna de las respuestas propuestas que mencionaban sobre Window.Owner
.
{
var newWindow = new AdditionalWindow();
newWindow.Owner = Window.GetWindow(this);
// then later on show the window with Show() or ShowDialog()
}
Una llamada a Window.GetWindow(this)
es bastante útil en Vista de una aplicación MVVM cuando se está lejos del árbol visual sin saber dónde ha sido instanciado, se puede invocar suministrando cualquier elemento FrameWork
(por ejemplo, UserContol
, Button
, Page
) Obviamente, si tiene una referencia directa a la ventana, entonces use eso o incluso Application.Current.MainWindow
.
Esta es una relación bastante poderosa que tiene una serie de beneficios útiles de los que quizás no se dé cuenta (suponiendo que no haya codificado ventanas separadas específicamente para evitar estas relaciones).
Si llamamos a su ventana principal MainWindow
y la segunda ventana como AdditionalWindow
entonces ....
- Minimizar
MainWindow
también minimizaráAdditionalWindow
- La restauración de
MainWindow
también restauraráAdditionalWindow
- Al cerrar
MainWindow
se cerraráAdditionalWindow
, pero al cerrarAdditionalWindow
no se cerraráMainWindow
-
AdditioanlWindow
nunca se "perderá" enMainWindow
, es decir,AddditionalWindow
siempre muestra arriba deMainWindow
en el orden z siAddditionalWindow
Show()
para mostrarlo (¡bastante útil!)
Una cosa a tener en cuenta, sin embargo, si tienes esta relación, entonces no se llama al evento Closing
en la OwnedWindows
AdditionalWindow
, por lo que tendrías que iterar manualmente sobre la colección OwnedWindows
. Por ejemplo, cree una forma de llamar a cada ventana a través de una nueva interfaz o método de clase base.
private void MainWindow_OnClosing(object sender, CancelEventArgs e)
{
foreach (var window in OwnedWindows)
{
var win = window as ICanCancelClosing; // a new interface you have to create
e.Cancel |= win.DoYouWantToCancelClosing();
}
}
Parece algo con lo que me encontré cuando creé una segunda ventana para actuar como un cuadro de diálogo. Cuando se abrió la segunda ventana y luego se cerró y luego se cerró la ventana principal, la aplicación siguió funcionando (en el fondo). Agregué (o confirmé) lo siguiente en mi App.xaml:
<Application x:Class="XXXXXXX.App"
...
StartupUri="MainWindow.xaml"
ShutdownMode="OnMainWindowClose">
<Application.MainWindow >
<NavigationWindow Source="MainWindow.xaml" Visibility="Visible" />
</Application.MainWindow>
Sin alegría.
Entonces, finalmente entré en mi "MainWindow.xaml" y agregué una propiedad "Closed" a la ventana que fue a un método "MainWind_Closed" que se parece a lo siguiente:
private void MainWind_Closed(object sender, EventArgs e)
{
foreach ( Window w in App.Current.Windows )
{
if (w.DataContext != this)
w.Close();
}
}
Al ejecutar el depurador, parece que la única ventana que aparece es la ventana que he creado como diálogo, en otras palabras, el bucle foreach solo encuentra una ventana, el diálogo, no el principal.
Tenía "this.Close ()" ejecutándose en el método que cerró el diálogo, y tuve un "dlgwin.Close ()" que vino después del "dlgwin.ShowDialog ()", y eso no funcionó. Ni siquiera un "dlgwin = null".
Entonces, ¿por qué ese diálogo no se cerraría sin estas cosas extra? Oh bien. Esto funciona.
Porque el modo de http://msdn.microsoft.com/en-us/library/system.windows.application.shutdownmode.aspx predeterminado en una aplicación WPF es OnLastWindowClose, lo que significa que la aplicación se detiene cuando se cierra la última ventana.
Cuando crea una instancia de un nuevo objeto Ventana, automáticamente se agrega a la lista de ventanas en la aplicación. Entonces, el problema era que su aplicación creaba dos ventanas cuando comenzó: MainWindow y Window01, que aún no se ha mostrado, y si solo cerraba MainWindow, Window01 mantendría su aplicación en ejecución.
Normalmente, creará un objeto de ventana en el mismo método que va a llamar a ShowDialog, y creará un nuevo objeto de ventana cada vez que se muestre el diálogo.