[WPF]如何在关闭非模态子窗体时用消息框确认——解决最小化窗体时抛出的异常

又是一个看起来很简单的问题。像下面这样在Closing里弹出个MessageBox确认一下不就行了?

 

public static void OnWindowClosing(object sender, CancelEventArgs e)
{
    
if (MessageBox.Show(string.Format("Are you sure to close the {0}?", (sender as Window).Title),
       
"Confirm", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.No)
    
{
        e.Cancel 
= true;
    }

}

代码简单得不能再简单了,而且试了一下可以达到目的,似乎是没有什么问题啊。但是很多代码需要大量的测试才能发现问题。这个代码就是其中之一。

 

在说明BUG之前,先给几个信息,大家可以猜猜如何重现这个问题。

1.       只有非模态的子窗体有这个BUG。主窗口是没有问题的。

2.       弹出MessageBox的时候,UI消息处理线程会被阻塞。

3.       抛出的异常,是InvalidOperationException

4.       子窗体与主窗体有从属关系,主窗体最小化时,子窗体也跟着最小化。

5.       最后一个信息,已经是把BUG告诉大家了。就是Error Message,如下图所示。

1. Exception信息

 

看了Error Message,应该都明白了。主窗体没有问题,因为关主窗体时弹出消息框之后,根本没有什么UI操作可以最小化主窗体。(自己写另一个程序去最小化这个窗体不在考虑范围之内。)所以不会有这个BUG,但是为什么子窗体有呢。

 

下面描述一个这个Bug的产生过程。

1.       主窗体和子窗体都显示出来。

2.       点击关闭按钮关闭子窗体,此时会弹出消息框问要不要关。不去理这个消息框。

3.       点击任务栏上的主窗体,使主窗体最小化。这里子窗体也最小化了。

4.       再点任务栏上的主窗体,使主窗体还原。异常抛出。而且,即使handle了这个异常,这个子窗体也会变黑的。

 

可以发现,其实罪魁祸首是上面的第4条信息。操作系统在主窗体最小化时,自动最小化其子窗体,结果帮了倒忙。这种自动做事帮倒忙的事情应该还有不少。还发现过的一例就是在WPF Bug清单里的RadioButton无法绑定的BUG,也是系统自动做事造成的。但是逻辑上来讲,这么做也的确是对的。

 

最后想办法解决问题的,只能是我们自己。ExceptionMessage上说在窗体Closing的时候,不能做这做那,但是我们又要做,那怎么办呢?其实是我们的MessageBox阻塞了窗体Close的过程才有这个异常。那么解决方案就出来,让MessageBox不阻塞UI线程不就得了。代码如下

 

public static void OnWindowClosingAdv(object sender, CancelEventArgs e)
{
    
Prevent Recursion

    e.Cancel 
= true//Cancel every close at once.

    Window window 
= sender as Window;
    window.Dispatcher.BeginInvoke(
new Action<Window>(ConfirmClose), window);
}


private static void ConfirmClose(Window window)
{
    
if (MessageBox.Show(string.Format("Are you sure to close the {0}?", window.Title),
        
"Confirm", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.Yes)
    
{
        window.Close();
    }

}

 

注:其中的Prevent Recursion代码段是为了防止递归调用的。完全可以用一个临时变量代码代替,而且不会出现硬编码的字符串。分析调用栈只是为了突出代码相对于原版的丑恶。^_^

 

这次还好,为了Fix系统的逻辑BUG,并没有多写多少代码。

 

 

 

 

原文地址:https://www.cnblogs.com/nankezhishi/p/1375945.html