Подтвердить что ты не робот

Приложение WPF не закрывается при закрытии главного окна

Я использую для программирования 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 ведет себя правильно - то есть отладка прекращается, когда я выхожу из приложения.

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

4b9b3361

Ответ 1

В 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) неявно вызывает Shutdown, когда последнее окно в приложении закрывается, даже если в качестве главного окна задано какое-либо текущее оконное окно (см. MainWindow).

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

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

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

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


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

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

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

Ответ 2

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


Шаг 1

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

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

В коде

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

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

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

В XAML

Перейдите в свой App.xaml файл, созданный по умолчанию (или создайте его самостоятельно) Корень - это 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

Перейдите в Application XAML, как и на шаге 1, и укажите, что Application. MainWindow значение Window:

MainWindow = "mainWindow";

Alternative

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

Перейдите в файл с кодом ниже, а затем добавьте:

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

        App.Current.Shutdown();
    }

Ответ 3

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

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

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

Ответ 4

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

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

Нет радости.

Итак, я, наконец, вошел в свой "MainWindow.xaml" и добавил свойство "Закрыто" в Окно, которое перешло к методу "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".

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

Ответ 5

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

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

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

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

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

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

  • Сведение к минимуму MainWindow также минимизирует AdditionalWindow
  • Восстановление MainWindow также восстановит AdditionalWindow
  • Закрытие MainWindow закрывает AdditionalWindow, но закрытие AdditionalWindow не закрывает MainWindow
  • 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();
        }        
    }