2017-11-01 3 views
-1

는 [나는 Catel 태그,하지만 난이 질문은 어떤 MVVM 프레임 워크에 적용되는 것 같아요.]WPF MVVM은 - 창 닫기 이벤트 디스플레이 메시지 박스는

특히에서 (닫기 이벤트를 처리하기위한이 웹 사이트에 대한 몇 가지 제안이 있습니다 프로그래머가 앱을 닫을 수 있는지 확인하거나 "Are you sure?"를 확인하기 위해 "빨간색 X"버튼을 누릅니다. 대화 상자. 저는 세 가지를 시도했습니다 -보기에서 이벤트를 완전히 처리하고 이벤트 트리거를 사용하여 XAML에서 ViewModel에 대한 명령을 호출하고 View에서 ViewModel 이벤트 처리기에 이벤트 처리를 연결하게했습니다. 사용자가 예상대로 창 닫기를 시도 할 때 세 가지 방법 모두 트리거됩니다. 그래서,

System.InvalidOperationException was unhandled 
Message: An unhandled exception of type 'System.InvalidOperationException' occurred in PresentationFramework.dll 
Additional information: Cannot set Visibility to Visible or call Show, ShowDialog, Close, or WindowInteropHelper.EnsureHandle while a Window is closing. 

내 메인 창을 닫는 창 :

내 문제는 내가 사용자의 확인을 얻을 수있는 이벤트 처리기에서 메시지 박스를 표시하려고하면, 나는 다음과 같은 예외를 얻을 수 있다는 것입니다 그것이 닫히면 내 애플 리케이션도 마찬가지다. CancelEventArgs.Cancel 값을 true로 설정하여 창 닫기를 취소 할 수 있다는 것을 알고 있습니다.

어떻게 닫히는 이벤트를 트래핑 한 다음 내 핸들러에서 사용자의 입력에 따라 실제로 닫을 지 여부를 결정하도록 할 수 있습니까?

자세한 정보가 필요하면 알려 주시기 바랍니다. 감사!

편집 : 여기가 종료 응용 프로그램 메뉴 명령을 처리하기 위해 사용하고있는 작업은 다음과 같습니다

private async void OnExitApplicationExecute() 
    if (this.IsProcessing) 
    { 
     await this._messageService.ShowWarningAsync("Please click on 'Stop Processing' before closing the Processor.", "Stop Processing First"); 
    } 
    else 
    { 
     MessageResult msgResult = await this._messageService.ShowAsync("Exiting the Processor will halt all request processing." + Environment.NewLine + "Are you sure?", 
      "Exiting Processor...", MessageButton.YesNo, MessageImage.Question); 
     if (msgResult == MessageResult.Yes) 
     { 
      _logger.Info("Main Task: Application ended."); 
      this._navigationService.CloseApplication(); 
     } 
    } 
} 

중에서 MessageService 및 navigationService 통화 Catel 서비스/방법이 있습니다. 로거는 NLog입니다.

이 기능은 모든 검사가 완료 될 때까지 창이 닫히지 않기 때문에 명령 처리기로 실행될 때 작동합니다. Closing 이벤트 처리의 일부로이 동일한 로직을 주입하려고하면 위에서 언급 한 예외가 발생합니다.

여기 스택 트레이스의 일부 : 나는 내 응용 프로그램/윈도우 개폐 과정을 관리 할 경우, 기본적으로

2017-11-01 14:45:57.3269 [00009] ERROR App: An unhandled exception occurred and has been logged. Please contact support. System.InvalidOperationException: Cannot set Visibility to Visible or call Show, ShowDialog, Close, or WindowInteropHelper.EnsureHandle while a Window is closing. 
at System.Windows.Window.VerifyNotClosing() 
at System.Windows.Window.InternalClose(Boolean shutdown, Boolean ignoreCancel) 
at System.Windows.Window.Close() 
at Catel.Windows.DataWindow.SetDialogResultAndMakeSureWindowGetsClosed(Nullable`1 result) in C:\CI_WS\Ws\105284\Source\Catel\src\Catel.MVVM\Catel.MVVM.Shared\Windows\Windows\DataWindow\DataWindow.cs:line 708 
at Catel.Windows.DataWindow.<OnDataWindowClosing>b__104_0() in C:\CI_WS\Ws\105284\Source\Catel\src\Catel.MVVM\Catel.MVVM.Shared\Windows\Windows\DataWindow\DataWindow.cs:line 892 
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) 
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler) 
+0

저는 종종 WPF의 주 창 WindowClosing 이벤트 처리기의 창에서 MessageBox 또는 ShowDialog를 호출합니다. 나는이 문제가 없었다. Windows, .NET 등의 버전은 무엇입니까? 그것을 재생산하는 최소한의 코드 샘플을 게시 할 수 있습니까? –

+0

이것을 재현 할 수 없습니다. 방금 WPF 응용 프로그램을 새로 만들었고'MessageBox.Show ("This is a test");를'MainWindow'의'Closing' 이벤트 처리기에 추가했습니다. 메시지 상자가 나타나고 오류는 없습니다. –

+0

더욱 복잡한 대화 상자에서 사용자에게 창을 정말로 닫으려고하는지 물어보고 닫기를 취소하면 오류가 없습니다. 우리는 여러분의 코드를 볼 필요가 있습니다. –

답변

0

, 나는 응용 프로그램 과정에서 직접 제어하려고합니다.

public partial class App : Application 
{ 
    public MainWindow window = new MainWindow(); 
    void App_Startup(object sender, StartupEventArgs e) 
    { 
     window.Show(); 
     window.Closing += manageClosing; 
    } 
    void manageClosing(Object sender, System.ComponentModel.CancelEventArgs e) 
    { 
     MessageBox.Show("It won't close"); 
     e.Cancel = true; 
    } 
} 
+0

응용 프로그램 수준에서는 ViewModel에 안전하게 닫히는 지 여부에 대한 지식이 없습니다. – RandyB

+0

VM은 임시 상태 만 보유해야하며 실제 데이터는 서비스/관리자에 저장되어야합니다. 이들은보기 모델간에 공유 할 수있는 오래 살아있는 객체이지만 상태가 특정 작업을 허용하는지 여부를 확인할 수있는 다른 서비스 (VM 외부!)도 있습니다. –

+0

참. 필자의 경우 View 및 ViewModel 만 있습니다. VM은 요청 프로세서 일뿐입니다. 요청을 찾아 BG 스레드에서 처리합니다. 필자는 모델이 없으며 처리를 위해 요청 데이터를 서비스로 전송할 수있는 소수의 POCO 클래스 만 있습니다. – RandyB

0

당신이 Catel을 사용하고 데이터 윈도우/윈도우 클래스를 사용하는 경우, 당신은 간단 MainViewModel::SaveAsync이 질문을 할 수 있습니다 여기에 몇 가지 매우 거친 코드입니다. false을 반환하면 창이 닫히지 않습니다 (Catel은 이미이 문제를 처리합니다).

+0

답장을 보내 주셔서 감사합니다. 사용자가 이탈 메뉴 항목을 클릭 할 때 검색어를 사용하여 원래 게시물을 수정했습니다. 이 논리를 SaveAsync 메서드를 재정의 (override) 할 수있게되었고, 그냥 내 ExitApplicationExecute 코드가 MainViewModel :: SaveAndCloseViewModelAsync를 호출하게되었습니다. 괜찮아. – RandyB

+0

그러나 사용자가 "X"닫기 버튼을 사용하여 창을 닫을 때이 코드는 호출되지 않습니다. 이 논리를 Closing 이벤트 핸들러로 이동하면 위와 같은 예외가 발생합니다. 애플리케이션을 닫고 사용자가 의도를 확인하도록 시도하려면 어떻게해야합니까? – RandyB

0

MessageBox을 표시하기 전에 CancelEventArgsCancel 속성을 true으로 설정하십시오. 이것은 나를 위해 잘 작동합니다 :

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     Closing += MainWindow_Closing; 
    } 


    private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) 
    { 
     e.Cancel = true; 

     if (MessageBox.Show("Do you want to close?", "", MessageBoxButton.YesNoCancel) == MessageBoxResult.Yes) 
      Environment.Exit(0); 
    } 
} 
+0

답장을 보내 주셔서 감사합니다. 나는 그것을 시도했지만 그것은 나를 위해 작동하지 않았다. Catel MVVM 프레임 워크를 사용하는 방법에 문제가 있다고 판단했습니다. – RandyB