[c#] 주 창을 닫을 때 WPF 앱이 종료되지 않음

저는 Visual Studio에서 WinForms 프로그래밍에 익숙하지만 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가 제대로 작동하는 것입니다. 즉, 응용 프로그램을 종료하면 디버깅이 중지됩니다.

왜 이렇게 이상한 행동을하나요?



답변

에서 다음을 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있는 현재 인스턴스화 창 메인 창으로 설정 한 경우에도 응용 프로그램 닫히고의 마지막 창 (MainWindow를 참조) 할 때, WPF (Windows Presentation Foundation)는 암시 적으로 종료를 호출합니다.

ShutdownModeOnMainWindowClose원인은 MainWindow를 닫히고는, 다른 창은 현재 열려있는 경우에도 때 암시 적으로 종료를 호출하는 WPF.

일부 응용 프로그램의 수명은 주 창 또는 마지막 창이 닫히는시기에 의존하지 않거나 창에 전혀 의존하지 않을 수 있습니다. 이러한 시나리오의 경우 ShutdownMode속성을 로 설정해야 합니다.이 경우 애플리케이션을 중지하려면 OnExplicitShutdown명시적인 Shutdown메서드 호출 이 필요합니다 . 그렇지 않으면 응용 프로그램이 백그라운드에서 계속 실행됩니다.

ShutdownMode XAML에서 선언적으로 또는 코드에서 프로그래밍 방식으로 구성 할 수 있습니다.

이 속성은 Application개체 를 만든 스레드에서만 사용할 수 있습니다 .


귀하의 경우 기본값을 사용하고 있기 때문에 앱이 닫히지 않습니다 OnLastWindowClose.

사용자가 설정 한 경우 ShutdownModeOnLastWindowClose어떤 현재 인스턴스 창 메인 창으로 설정 한 경우에도 응용 프로그램 닫히고의 마지막 창 (볼 때, WPF는 암시 적으로 종료를 호출 MainWindow).

새 창을 열고 닫지 않기 때문에 shutdown이 호출되지 않습니다.


답변

답변을 받으 셨다니 기쁩니다.하지만 다른 사람들을 위해 질문에 답하여 정보를 추가하겠습니다.


1 단계

첫째, 주 창이 닫힐 때 프로그램을 종료하려면이 동작이 기본값 인 WinForms가 아니므로 지정해야합니다.

(WPF의 기본값은 마지막 창이 닫힐 때입니다.)

코드에서

진입 점의 애플리케이션 인스턴스로 이동합니다 (VS 2012의 WPF 프로그램에서 기본값은 내부 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에서

Application1 단계에서했던 것처럼 XAML로 이동하여 Application. MainWindow의 가치는 다음과 Window같습니다.

MainWindow = "mainWindow";

대안

WPF가이 작업을 원하지 않기 때문에 이것이 최선의 방법이라고 생각하지 않습니다 (그래서 Application‘s가 있습니다 ShutdownMode).하지만 이벤트를 사용하거나 이벤트 메서드 (OnEventHappened)를 재정의 할 수 있습니다.

MainWindow의 코드 숨김 파일로 이동하여 다음을 추가합니다.

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

        App.Current.Shutdown();
    }


답변

WPF 응용 프로그램 의 기본 종료 모드 는 OnLastWindowClose이므로 마지막 창이 닫힐 때 응용 프로그램이 중지됩니다.

새 Window 개체를 인스턴스화하면 자동으로 응용 프로그램 의 창 목록에 추가됩니다 . 따라서 문제는 응용 프로그램이 시작될 때 MainWindow와 아직 표시되지 않은 Window01이라는 두 개의 창을 만들고 MainWindow 만 닫으면 Window01이 응용 프로그램을 계속 실행한다는 것입니다.

일반적으로 ShowDialog를 호출 할 동일한 메서드로 창 개체를 만들고 대화 상자가 표시 될 때마다 새 창 개체를 만듭니다.


답변

나는 다른 것을 검색 할 때이 질문을 우연히 발견했고에 대해 언급 된 제안 된 답변을 볼 수 없다는 것에 놀랐습니다 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항상 MainWindowz 순서로 위에 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();
        }
    }


답변

위의 어느 것도 저에게 효과가 없었습니다. 아마도 우리 프로젝트가 Prism을 사용하기 때문일 것입니다. 그래서 App.XAML.cs에서 이것을 사용했습니다.

    protected override void OnExit(ExitEventArgs e)
    {
        base.OnExit(e);
        Process.GetCurrentProcess().Kill();
    }


답변

대화 상자 역할을 할 두 번째 창을 만들 때 만난 것 같습니다. 두 번째 창이 열렸다가 닫히고 메인 창이 닫 혔을 때 앱은 계속 실행되었습니다 (백그라운드에서). 내 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”메소드로 이동 한 “Closed”속성을 Window에 추가했습니다.

 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.ShowDialog ()”다음에 오는 “dlgwin.Close ()”가 있는데 작동하지 않았습니다. “dlgwin = null”도 아닙니다.

그렇다면이 추가 항목 없이는 대화 상자가 닫히지 않는 이유는 무엇입니까? 오 잘. 작동합니다.


답변