L'application WPF ne S'éteint pas lors de la fermeture de la fenêtre principale

j'ai l'habitude de Winformer la programmation dans Visual Studio, mais je voulais donner à WPF un essai.

j'ai ajouté une autre fenêtre à mon projet, appelée Window01. La fenêtre principale est appelée MainWindow. Avant le constructeur public MainWindow() je déclare Window01:

Window01 w1;

maintenant j'instancie cette fenêtre dans:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    w1 = new Window01();            
}

j'ai un bouton où la fenêtre est affiché: w1.ShowDialog(); .

La " drôle de chose voici le fait que si je démarre L'application (avec Débogage) et que je la quitte quelques secondes après (Je ne fais rien dans l'application), Visual Studio n'arrête pas de déboguer comme si l'application était toujours en cours d'exécution.

si je déplace la ligne w1 = new Window01(); à la méthode de clic de bouton, signifiant juste au - dessus de ShowDialog() , Visual Studio se comporte correctement-c'est-à-dire, le débogage s'arrête quand je sors de l'application.

Pourquoi ce comportement étrange?

62
demandé sur Bob Horn 2012-04-03 15:14:26

5 réponses

dans votre MainWindow.xaml.cs , essayez de faire ceci:

protected override void OnClosed(EventArgs e)
{
    base.OnClosed(e);

    Application.Current.Shutdown();
}

par ce lien, vous pouvez également définir le ShutdownMode dans 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>
Les Applications

cessent de fonctionner uniquement lorsque la méthode Shutdown de la Application est appelée. L'arrêt peut se produire implicitement ou explicitement, comme spécifié par la valeur de la propriété ShutdownMode .

si vous définissez ShutdownMode à OnLastWindowClose , Windows Presentation Foundation (WPF) appelle implicitement Shutdown lorsque la dernière fenêtre d'une application se ferme, même si des fenêtres actuellement instanciées sont définies comme la fenêtre principale (voir MainWindow).

Un ShutdownMode de OnMainWindowClose causes WPF implicitement appel à l'Arrêt quand le MainWindow ferme, même si d'autres fenêtres actuellement ouvertes.

La durée de vie de certaines applications peuvent ne pas être dépendante lorsque la fenêtre principale ou la fenêtre est fermée, ou peut ne pas être dépendant de windows. Pour ces scénarios, vous devez définir la propriété ShutdownMode à OnExplicitShutdown , ce qui nécessite un appel de méthode explicite Shutdown pour arrêter l'application. Sinon, l'application continue à tourner en arrière-plan.

ShutdownMode peut être configuré de manière déclarative à partir de XAML ou programmatiquement à partir de code.

cette propriété est disponible uniquement à partir du thread qui a créé l'objet Application .


dans votre cas, l'application ne se ferme pas car vous utilisez probablement la valeur par défaut OnLastWindowClose :

si vous définissez ShutdownMode à OnLastWindowClose , WPF appelle implicitement Shutdown lorsque la dernière fenêtre d'une application se ferme, même si n'importe quelle fenêtre actuellement instanciée est définie comme la fenêtre principale (voir MainWindow ).

comme vous ouvrez une nouvelle fenêtre et que vous ne la fermez pas, shutdown n'est pas appelé.

108
répondu Bob Horn 2017-05-19 12:44:37

je suis heureux que vous avez eu votre réponse, mais pour le bien des autres je vais répondre à votre question ainsi-bien d'ajouter quelques informations.


Étape 1

tout d'abord, si vous voulez que votre programme se termine lorsque la fenêtre principale se ferme, vous devez spécifier, car ce n'est pas WinForms où ce comportement est par défaut.

(La valeur par défaut dans WPF, c'est quand la dernière fenêtre se ferme)

Dans Le Code

allez à l'instance de votre application dans votre point d'entrée (dans le programme WPF de VS 2012 , la valeur par défaut est imbriquée dans App.xaml , alors allez à dans it et naviguez vers App.xaml.cs et créez un constructeur).

Dans le constructeur de préciser que votre Application 's ShutdownMode doit être ShutdownMode . OnLastWindowClose .

    public App()
    {
        ShutdownMode = ShutdownMode.OnLastWindowClose;
    }

Dans le code XAML

allez à votre fichier App.xaml que VS 2012 Créé par défaut (ou créez-le vous-même)) La racine est un Application , spécifiez à l'intérieur que votre Application 's ShutdownMode devrait être 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 elle fonctionne, vous avez terminé; vous pouvez arrêter de lire.


l'Étape 2

si ce qui précède n'a pas fonctionné (je suppose que vous avez écrit l'application WPF à partir de zéro), la fenêtre principale n'est probablement pas connue de l'application comme la fenêtre principale. Afin de spécifier que bien.

Dans Le Code

allez au constructeur de l'application comme vous l'avez fait à L'Étape 1, et spécifiez que Application . MainWindow 's valeur est votre Window :

MainWindow = mainWindow;

Dans le code XAML

allez au Application XAML comme vous l'avez fait à L'Étape 1, et précisez que Application . MainWindow 's valeur est votre Window :

MainWindow = "mainWindow";

Alternative

Je ne pense pas que ce soit la meilleure approche, juste parce que WPF ne veut pas que vous fassiez cela (donc il a Application 's ShutdownMode ), mais vous pouvez simplement utiliser une méthode event / override an event (OnEventHappened).

allez dans le fichier de code de la fenêtre principale et ajoutez:

    protected override void OnClosed(EventArgs e)
    {
        base.OnClosed(e);

        App.Current.Shutdown();
    }
23
répondu MasterMastic 2012-12-11 12:55:52

parce que la valeur par défaut mode d'arrêt dans une application WPF est OnLastWindowClose, ce qui signifie que l'application s'arrête lorsque la dernière fenêtre se ferme.

lorsque vous instanciez un nouvel objet Window, il est automatiquement ajouté à la liste de windows dans l'application. Donc, le problème était que votre application créait deux fenêtres quand elle a commencé - le MainWindow et le Window01 non-encore montré - et si vous seulement la fenêtre MainWindow fermée, la Window01 garderait votre application en marche.

normalement, vous allez créer un objet fenêtre dans la même méthode qui va appeler son ShowDialog, et vous allez créer un nouvel objet fenêtre à chaque fois que la boîte de dialogue est affichée.

10
répondu Joe Daley 2012-04-03 12:14:40

il ressemble à quelque chose que j'ai rencontré quand j'ai créé une deuxième fenêtre pour agir comme une boîte de dialogue. Lorsque la deuxième fenêtre a été ouverte puis fermée et que la fenêtre principale a été fermée, l'application a continué à fonctionner (en arrière-plan). J'ai ajouté (ou confirmé) ce qui suit dans mon application.xaml:

<Application x:Class="XXXXXXX.App"
             ...  
             StartupUri="MainWindow.xaml"
             ShutdownMode="OnMainWindowClose">
    <Application.MainWindow >
        <NavigationWindow Source="MainWindow.xaml" Visibility="Visible" />
    </Application.MainWindow>

Pas de joie.

donc, je suis finalement allé dans mon" MainWindow.xaml "et a ajouté une propriété "fermée" à la fenêtre qui est passée à une méthode "MainWind_Closed" cela ressemble à ce qui suit:

 private void MainWind_Closed(object sender, EventArgs e)
        {
            foreach ( Window w in App.Current.Windows )
            {
                if (w.DataContext != this)
                    w.Close();
            }
        }

passant par le débogueur, on dirait que la seule fenêtre qui s'affiche est la fenêtre que j'ai créée en dialogue--en d'autres termes, la boucle foreach ne trouve qu'une fenêtre--la boîte de dialogue, pas la main.

j'ai eu ".Fermer () "en cours d'exécution dans la méthode qui a clos le dialogue, et j'ai eu un" dlgwin.Close () " qui est venu après le dlgwin.ShowDialog()", et qui n'a pas fonctionné. Pas même un "dlgwin = null".

alors, pourquoi ce dialogue ne se fermerait-il pas sans ces trucs supplémentaires? Oh bien. Les travaux de cette.

0
répondu Lowell 2016-04-07 01:18:06

je suis tombé sur cette Question en cherchant quelque chose d'autre et j'ai été surpris de ne voir aucune des réponses proposées mentionnant Window.Owner .

    {
       var newWindow = new AdditionalWindow();
       newWindow.Owner = Window.GetWindow(this);

       // then later on show the window with Show() or ShowDialog()
    }

un appel à Window.GetWindow(this) est très utile en vue d'une application MVVM lorsque vous êtes loin dans l'arbre visuel ne sachant pas où vous avez été instancié, il peut être appelé en fournissant n'importe quel élément FrameWork (par ex. UserContol , Button , Page ). Évidemment, si vous avez une référence directe à la fenêtre, puis l'utiliser ou même Application.Current.MainWindow .

c'est une relation assez puissante qui a un certain nombre d'avantages utiles que vous pourriez ne pas réaliser pour commencer (en supposant que vous n'avez pas spécifiquement codé des fenêtres séparées pour éviter ces relations).

si nous appelons votre fenêtre principale MainWindow et la deuxième fenêtre AdditionalWindow alors....

  1. La minimisation du MainWindow minimisera également le AdditionalWindow
  2. restauration MainWindow restaurera également AdditionalWindow
  3. fermeture MainWindow fermera AdditionalWindow , mais la fermeture AdditionalWindow ne fermera pas MainWindow
  4. AdditioanlWindow ne sera jamais "perdu" sous MainWindow , i.e. AddditionalWindow montre toujours au-dessus de MainWindow dans l'ordre z si vous avez utilisé Show() pour l'afficher (très utile!)

une chose à noter cependant, si vous avez cette relation, alors l'événement Closing sur le AdditionalWindow n'est pas appelé, donc vous devez itérer manuellement sur la collection OwnedWindows . par exemple, créez une façon d'appeler chaque fenêtre via une nouvelle Interface, ou une méthode de classe de 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();
        }        
    }
0
répondu Rhys 2016-07-27 15:02:00