Приложение WPF не закрывается при закрытии главного окна - PullRequest
64 голосов
/ 03 апреля 2012

Я привык к программированию на WinForms в Visual Studio, но я хотел попробовать WPF.

Я добавил еще одно окно в мой проект, которое называется Window01. Главное окно называется MainWindow. Перед конструктором public MainWindow() я объявляю Window01:

Window01 w1;

Теперь я создаю экземпляр этого окна в:

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

У меня есть кнопка, где отображается окно: w1.ShowDialog();.

Самое забавное здесь в том, что если я запускаю приложение (с отладкой) и выхожу из него через несколько секунд (я ничего не делаю в приложении), Visual Studio не прекращает отладку, как будто приложение все еще работает.

Если я переместу строку w1 = new Window01(); к методу нажатия кнопки, то есть чуть выше ShowDialog(), Visual Studio будет работать правильно, то есть отладка прекращается при выходе из приложения.

Почему это странное поведение?

Ответы [ 5 ]

115 голосов
/ 03 апреля 2012

В вашем MainWindow.xaml.cs попробуйте сделать это:

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

    Application.Current.Shutdown();
}

По этой ссылке вы также можете установить ShutdownMode в 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>

Приложения останавливаются только при вызове Shutdown метода Application. Завершение работы может происходить неявно или явно, как указано в значении свойства ShutdownMode.

Если для ShutdownMode установлено значение OnLastWindowClose, Windows Presentation Foundation (WPF) неявно вызывает завершение работы, когда закрывается последнее окно в приложении, даже если в качестве основного окна заданы какие-либо экземпляры, созданные в данный момент (см. MainWindow).

A ShutdownMode из OnMainWindowClose заставляет WPF неявно вызывать Shutdown при закрытии MainWindow, даже если в настоящее время открыты другие окна.

Время жизни некоторых приложений может не зависеть от того, когда закрыто главное или последнее окно, или вообще не зависеть от окон. Для этих сценариев необходимо установить для свойства ShutdownMode значение OnExplicitShutdown, что требует явного вызова метода Shutdown для остановки приложения. В противном случае приложение продолжает работать в фоновом режиме.

ShutdownMode может быть настроен декларативно из XAML или программно из кода.

Это свойство доступно только из потока, создавшего объект Application.


В вашем случае приложение не закрывается, потому что вы, вероятно, используете значение по умолчанию OnLastWindowClose:

Если вы установите для ShutdownMode значение OnLastWindowClose, WPF неявно вызовет завершение работы, когда закроется последнее окно в приложении, даже если в качестве основного окна установлены какие-либо экземпляры, созданные в данный момент (см. MainWindow).

Поскольку вы открываете новое окно, а не закрываете его, отключение не вызывается.

25 голосов
/ 11 декабря 2012

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


Шаг 1

Во-первых,если вы хотите, чтобы ваша программа закрывалась при закрытии главного окна, вам нужно указать, так как это не WinForms, где это поведение по умолчанию.

(По умолчанию в WPF закрывается последнее окновниз)

В коде

Перейдите к экземпляру приложения в точке входа (в программе WPF VS 2012 по умолчанию вложено в App.xaml, поэтомуперейдите внутрь и перейдите к App.xaml.cs и создайте конструктор).

В конструкторе укажите, что ваши Application ShutdownMode должно быть ShutdownMode. OnLastWindowClose.

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

В XAML

Перейти к вашему App.xaml файлу, которыйVS 2012 создан по умолчанию (или создайте его самостоятельно). Корень - Application, укажите внутри, что ваш Application * ShutdownMode должен быть 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">

Если все работает, все готово;Вы можете прекратить чтение.


Шаг 2

Если вышеприведенное не сработало (я думаю, вы написали приложение WPF с нуля), вероятно, главное окно неизвестноприложение в качестве основного окна.Поэтому укажите это также.

В коде

Перейдите к конструктору приложения, как вы это делали в шаге 1, и укажите, что Application. MainWindow - это ваше Window:

MainWindow = mainWindow;

В XAML

Goк Application XAML, как вы делали на шаге 1, и укажите, что значение Application. MainWindow является вашим Window:

MainWindow = "mainWindow";

Альтернатива

Я не думаю, что это лучший подход, просто потому, что WPF не хочет, чтобы вы это делали (поэтому он имеет Application ShutdownMode), но вы можете просто использовать событие / переопределить метод события (OnEventHappened).

Перейдите в файл кода MainWindow и добавьте:

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

        App.Current.Shutdown();
    }
11 голосов
/ 03 апреля 2012

Поскольку по умолчанию режим выключения в приложении WPF - OnLastWindowClose, это означает, что приложение останавливается при закрытии последнего окна.

При создании нового объекта Window оно автоматически добавляетсяв список окон в приложении.Таким образом, проблема заключалась в том, что ваше приложение создавало два окна при запуске - MainWindow и еще не показанное Window01 - и если вы только закрыли MainWindow, Window01 продолжит работу приложения.

Обычно, вы создадите объект окна в том же методе, который будет вызывать его ShowDialog, и создадите новый объект окна каждый раз, когда отображается диалоговое окно.

0 голосов
/ 27 июля 2016

Я наткнулся на этот вопрос, когда искал что-то еще, и я был удивлен, что не увидел ни одного из предложенных ответов, в которых упоминалось бы о Window.Owner.

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

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

.полезно в представлении приложения MVVM, когда вы находитесь далеко внизу визуального дерева, не зная, где вы были созданы, его можно вызвать, указав любой элемент FrameWork (например, UserContol, Button, Page).Очевидно, что если у вас есть прямая ссылка на окно, используйте это или даже Application.Current.MainWindow.

Это довольно мощные отношения, которые имеют ряд полезных преимуществ, которые вы, возможно, не осознали с самого начала (если предположить, чтоотдельно не кодируются отдельные окна, чтобы избежать этих взаимосвязей).

Если мы называем ваше главное окно MainWindow, а второе окно как AdditionalWindow, тогда ....

  1. МинимизацияMainWindow также уменьшит AdditionalWindow
  2. Восстановление MainWindow также восстановит AdditionalWindow
  3. Закрытие MainWindow закроет AdditionalWindow, но закрытие AdditionalWindow не закроется MainWindow
  4. AdditioanlWindow никогда не будет "потеряно" при MainWindow, то есть AddditionalWindow всегда показывает выше MainWindow в z-порядке, если вы использовали Show() для его отображения (весьма полезно!)

Следует отметить одну вещь: если у вас есть эта связь, то событие Closing в AdditionalWindow не вызывается, поэтому вам придется вручную выполнять итерацию по OwnedWindowsколлекция.например, создать способ вызова каждого окна через новый интерфейс или метод базового класса.

    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 голосов
/ 07 апреля 2016

Похоже на то, с чем я столкнулся, когда создал второе окно в качестве диалогового окна.Когда второе окно открывалось, а затем закрывалось, а затем закрывалось главное окно, приложение продолжало работать (в фоновом режиме).Я добавил (или подтвердил) следующее в своем App.xaml:

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

Без радости.

Итак, я наконец-то вошел в свой «MainWindow.xaml» и добавил «Закрыто»Свойство Window, которое перешло к методу MainWind_Closed, которое выглядит следующим образом:

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

При запуске через отладчик, похоже, что единственное окно, которое отображается, это окно, которое я создал как диалоговое окно.Другими словами, цикл foreach находит только одно окно - диалоговое окно, а не главное.

У меня был метод this.Close (), запущенный в методе, закрывшем диалог, и у меня было "dlgwin.Close () ", которая пришла после" dlgwin.ShowDialog () ", и это не сработало.Даже не "dlgwin = null".

Итак, почему этот диалог не закрылся бы без этого лишнего материала?Ну что ж.Это работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...