使用“X”按钮或ESC键关闭WPF窗口时的确认

如何通过单击“X”按钮或按ESC键关闭桌面应用程序中的WPF窗口时请求确认?
我想用最少的代码来实现它。
类似的问题在这里,但在MVVM Light和代码太多。

利用OnClosing虚拟方法:

 protected override void OnClosing(CancelEventArgs e) { // show the message box here and collect the result // if you want to stop it, set e.Cancel = true e.Cancel = true; } 

内部代码可能如下所示:

 var result = MessageBox.Show(...); if (result == DialogResult.{SomeEnumVal}) { e.Cancel = true; } 

我一直在寻找更多的MVVM方式。 所以这对我有用。

窗口代码

       

背后的代码

 ///  /// Handles the Closing event of the Window control. ///  /// The source of the event. /// The  instance containing the event data. private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { e.Cancel = !_viewModel.ShouldCloseApp; } 

视图模型中的命令

 public bool ShouldCloseApp { get; private set; } private RelayCommand _exitApplicationCommand; public RelayCommand ExitApplicationCommand { get { if (_exitApplicationCommand == null) { _exitApplicationCommand = new RelayCommand(exitApplicationCommand); } return _exitApplicationCommand; } } ///  /// This closes a specified window. If you pass the main window, then this application /// will exit. This is because the application shut down mode is set to OnMainWindowClose. ///  /// The window to close. private void exitApplicationCommand(Window window) { try { DialogService.ShowConfirmation( UIStrings.MainWindowViewModel_ExitProgramHeader, UIStrings.MainWindowViewModel_ExitProgramMessage, UIStrings.MainWindowViewModel_ExitProgramAcceptText, UIStrings.MainWindowViewModel_ExitProgramCancelText, (DialogResult result) => { if ((result.Result.HasValue) && (result.Result.Value)) { if (ElectroTekManager.Manager.ConnectedElectroTek != null) { SendToStatusOperation operation = new SendToStatusOperation(ElectroTekManager.Manager.ConnectedElectroTek, (operationResult, errorMessage) => { if (operationResult != FirmwareOperation.OperationResult.Success) { log.Debug(string.Format("{0} {1}", CautionStrings.MainWindowViewModel_LogMsg_UnableToSendToStatus, errorMessage)); } else if (!string.IsNullOrEmpty(errorMessage)) { log.Debug(errorMessage); } Application.Current.Dispatcher.Invoke(new Action(() => closeApp(window))); }); operation.Execute(); } else { closeApp(window); } } }); } catch (Exception ex) { log.Debug(CautionStrings.MainWindowViewModel_LogMsg_FailedToShowConfirmation, ex); } } ///  /// Closes the application. ///  /// The window. private void closeApp(Window window) { ShouldCloseApp = true; Dispose(); Application.Current.Shutdown(); } 

确认后,我调用Application.Current.Shutdown()。 这会在第二次触发代码中的关闭事件,但不会再次触发exit命令。

我发现IMHO 很好的解决方案与附加行为。 添加此function是仅向window-tag添加一个名称空间和一个属性:

MainWindow.xaml

  ...  

行为类中的其他所有内容:

 private static void OnValueChange(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (!(d is Window)) { return; } var window = d as Window; if ((bool)e.NewValue) { InputBinding escapeBinding = new InputBinding(AppCommands.WindowCloseCommand, new KeyGesture(Key.Escape)); escapeBinding.CommandParameter = window; window.InputBindings.Add(escapeBinding); window.Closing += Window_Closing; } else { window.Closing -= Window_Closing; } } static void Window_Closing(object sender, CancelEventArgs e) { #if DEBUG #else e.Cancel = MessageBox.Show(window, "Are you sure?", "Exit", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.Yes; #endif }