it-swarm.com.ru

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

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

64
eightx2

В вашем 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>

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

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

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

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

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

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


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

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

Так как вы открываете новое окно, а не закрываете его, shutdown не вызывается.

113
Bob Horn

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


Шаг 1

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

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

В коде

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

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

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

В XAML

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

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

MainWindow = "mainWindow";

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

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

Перейдите к файлу с выделенным кодом MainWindow и добавьте:

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

        App.Current.Shutdown();
    }
25
MasterMastic

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

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

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

11
Joe Daley

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

  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
Rhys

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

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

Нет радости.

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

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

0
Lowell