Подтверждение при закрытии окна WPF кнопкой " X " или ESC-клавишей
Как я могу запросить подтверждение при закрытии окна WPF в настольном приложении с помощью кнопки " X " или нажав клавишу ESC?
Я хотел бы сделать это с минимумом кода.
Похожая проблема здесь но на MVVM свет и слишком много кода.
3 ответов
использовать 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 способ сделать это. Вот что сработало для меня.
окне код
<Window x:Class="My.Namespace.Wpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
mc:Ignorable="d"
Closing="Window_Closing">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<i:InvokeCommandAction Command="{Binding ExitApplicationCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
код
/// <summary>
/// Handles the Closing event of the Window control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.ComponentModel.CancelEventArgs"/> instance containing the event data.</param>
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = !_viewModel.ShouldCloseApp;
}
команды в модели представления
public bool ShouldCloseApp { get; private set; }
private RelayCommand<Window> _exitApplicationCommand;
public RelayCommand<Window> ExitApplicationCommand
{
get
{
if (_exitApplicationCommand == null)
{
_exitApplicationCommand = new RelayCommand<Window>(exitApplicationCommand);
}
return _exitApplicationCommand;
}
}
/// <summary>
/// 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.
/// </summary>
/// <param name="window">The window to close.</param>
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);
}
}
/// <summary>
/// Closes the application.
/// </summary>
/// <param name="window">The window.</param>
private void closeApp(Window window)
{
ShouldCloseApp = true;
Dispose();
Application.Current.Shutdown();
}
после подтверждения я вызываю приложение.Текущий.Выключение.)( Это запускает событие закрытия в коде во второй раз, но не запускает команду exit снова.
AI нашел IMHO хорошее решение с приложенными поведения. Добавление этой функции заключается в добавлении только одного пространства имен и одного атрибута в window-tag:
файл MainWindow.в XAML
<Window x:Class="WpfClosingByEscape.MainWindow"
...
xmlns:bhv="clr-namespace:WpfClosingByEscape.Behaviors"
bhv:WindowClosingBehavior.Enabled="True"
>
...
</Window>
все остальное в поведении-класс:
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
}