WPF:以编程方式关闭窗口而不触发Window_Closing()

时间:2017-09-13 07:20:21

标签: c# wpf

我正在创建一个应用程序,用户可以根据需要动态创建更多窗口。应用程序始终具有一个 MainWindow实例,并且将具有0个或更多AuxWindow实例。

添加更多AuxWindow实例可以正常工作。但是我遇到了以编程方式再次关闭它们的问题(即,如果用户想要减少辅助窗口的数量)。从AuxWindow VM调用AuxWindow.Close()也会触发Window_Closing()方法,该方法开始要求用户进行确认。

那么如何区分关闭窗口的用户和执行该操作的应用程序呢?如果用户关闭窗口,我想要求确认,然后关闭整个应用程序。但是如果应用程序正在关闭窗口,我只想关闭它。

这里是AuxWindow中的Window_Closing()方法:

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
    _logger.Info("Exit application initiated - closing window");
    var result = _auxWindowVM.Controller.ExitApplication(this);
    if (result == false) {
        _logger.Info("Closing application confirmed");
        e.Cancel = false;
    }
    else {
        _logger.Info("Closing application canceled");
        e.Cancel = true;
    }
}

这是从MainWindow和所有AuxWindow实例调用的ExitApplication方法:

public bool ExitApplication(Window initWindow) {
    if (_exitConfirmed == false) {
        if (System.Windows.MessageBox.Show("Are you sure you want to exit?", "", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Question, System.Windows.MessageBoxResult.No) == System.Windows.MessageBoxResult.Yes) {
            MainWindowVM.CurrentDateTimeUpdateTimer.Stop();
            SerialPortHandler.SerialPortCts.Cancel();
            ArgusMk2CommProtocol.QueueConsumerCts.Cancel();
            PollingHandler.PollingTimer.Stop();
            _exitConfirmed = true;
            Application.Current.Shutdown();
            return false;
        }
        else {
            return true;
        }
    }
    else {
        return false;
    }
}

1 个答案:

答案 0 :(得分:2)

我会为AuxWindow引入一个接口来处理这个问题。 (为什么是界面?只是为了确保视图与视图模型之间没有紧密耦合,请参阅MVVM和SOLID。)

interface ICloseableView
{
    void Close(bool confirmClose);
}

然后我会在我的视图中实现这个界面:

class AuxWindow : Window, ICloseableView
{
    private bool confirmClose = true;

    public void Close(bool confirmClose)
    {
        try
        {
            this.confirmClose = confirmClose;
            Close();
        }
        finally
        {
            this.confirmClose = true;
        } 
    }

    private void Window_Closing(object sender, CancelEventArgs e)
    {
        if (!this.confirmClose)
        {
            e.Cancel = false;
            return;
        }

        // Your code here...
    }

}

最后,在AuxWindow的视图模型中,我将使用此方法通过接口引用获取它。请记住:视图模型不应该知道具体的视图实现,因此提供带有AuxWindow引用的视图模型是不好的做法,但是给它一个{是完全可以的。 {1}}参考:

IClosableView

使用这种方法,只要用户在正常情况下关闭class AuxWindowViewModel : INotifyPropertyChanged { private readonly IClosableView view; // E.g. use a dependency injection via constructor public AuxWindowViewModel(IClosableView view) { this.view = view; } void CloseViewWithoutConfirmation() { this.view.Close(false); } } ,就会始终收到确认对话框。通过GUI或键盘快捷方式的方式。但是从视图模型中关闭视图不会显示该对话框。