C# WPF:以编程方式关闭窗口而不触发窗口关闭()
我正在制作一个应用程序,用户可以根据自己的需要动态创建更多的窗口。应用程序始终有一个MainWindow实例,并且将有0个或多个AuxWindow实例 添加更多的AuxWindow实例效果很好。但我在以编程方式再次关闭它们时遇到了问题(即,如果用户希望减少辅助窗口的数量)。从AuxWindow VM调用AuxWindow.Close()也会触发Window_Closing()方法,该方法开始请求用户确认 那么,我如何区分关闭窗口的用户和执行此操作的应用程序呢?如果用户关闭窗口,我想请求确认,然后关闭整个应用程序。但是如果应用程序正在关闭窗口,我只希望它关闭 以下是AuxWindow中的Window_Closing()方法:C# WPF:以编程方式关闭窗口而不触发窗口关闭(),c#,wpf,C#,Wpf,我正在制作一个应用程序,用户可以根据自己的需要动态创建更多的窗口。应用程序始终有一个MainWindow实例,并且将有0个或多个AuxWindow实例 添加更多的AuxWindow实例效果很好。但我在以编程方式再次关闭它们时遇到了问题(即,如果用户希望减少辅助窗口的数量)。从AuxWindow VM调用AuxWindow.Close()也会触发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;
}
}
我将为
AuxWindow
s引入一个接口来处理这个问题。(为什么是界面?为了确保视图和视图模型之间没有紧密耦合,请参见MVVM和SOLID。)
然后我将在我的视图中实现此接口:
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
引用是一种不好的做法,但为其提供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或键盘快捷键以“正常”方式关闭
AuxWindow
时,都会得到一个确认对话框。但是从视图模型关闭视图不会显示该对话框。使用局部布尔值检查操作符是否需要确认的好主意。但是,我如何在没有引用的情况下从VM实例化一个视图(我已经被告知这是一种“正确”的方式(这是错误的吗?)?当前,在VM构造函数中实例化视图时,我将VM作为参数传递,然后在视图构造函数中将VM设置为视图DataContext。对还是错?一般来说,视图模型不应该关心它的视图——这是MVVM范例的核心原则。这个话题相当复杂。你可以阅读更多关于它的信息,例如,在这里做一些研究,或者只是问另一个关于它的问题。谢谢你提供的信息。
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);
}
}