[WPF Bug清单]之(5)——隐藏模态对话框后变成非模态

发现这个问题时,隐约记得之前有人已经发过这个问题,想把链接放到这里,不过找了半天,实在找不到。日后如果找到了一定加上。

问题描述:ShowDialog方法弹出一个模态对话框,然后将此对话框的Visibility属性设置为Hidden,再设置回Visible,发现这个对话框已经不是模态的了。

有人会觉得关就关了得了,也不会有这个问题,干什么要把Close取消掉然后再显示出来呢?因为这是有应用环境的。

应用环境:有些对话框,从逻辑上就是单例的,比如OfficeVisual Studio里都有的查找对话框,显然没有必要同时显示两个。而且也没有必要每次重新实例化并显示出来,在用户关闭窗体时,将窗体隐藏起来会更好,这样上次查找的关键字还存在着。可以省去一些代码保存这个历史关键字。

当然,这种方式也会有不好的地方,欢迎大家指摘。

写了一个程序来模拟这个Bug,效果如下面三张图所示。

1. 主窗体,点第一个按钮

 

2. 弹出的模态对话框,点击按钮将自己隐藏

 

3. 再点击主窗体的最后一个按钮,显示出来,已经是非模态对话框了

以前发Bug,一般没有去看过.NET的源代码,这次感觉这个Bug 有点儿太不应该了,就看了看源代码,发现WPF还特意为Dialog(模态的)Hidden做了单独的处理,感觉就更不应该有问题了,我们来看看源代码。

DoDialogHide

其中直接把_showingAsDialog设置为了false,当再次把窗体的Visibility设置为Visible的时候,Window类又会根据这个变量的值来判断是否将窗体按模态的方式显示出来。而MS对这行代码的的注释仅仅是“// clears _showingAsDialog”。

从源代码上来看,WPFWindow似乎是使用下面的代码将一个窗体从非模态变成模态的。

SetAsModal

但是当我自己在使用里使用这个方法的时候,却发现根本达不到目的。后来突然想到一个方法,试了一下,就可以。解决方法是,不使用Visibility = Visible,使窗体再次显示出来。而且再调用一次ShowDialog方法来显示这个窗体。这个方法也许只有对WPF不熟悉或是非常熟悉的人才能想得出来(我是死马当作活马医碰对了),因为正常情况下,继续地第二次调用ShowDialog方法是会抛出异常的。类似的诡异的Window的异常在[WPF]如何在关闭非模态子窗体时用消息框确认——解决最小化窗体时抛出的异常里也有描述。

另外,在非UI线程弹出的MessageBox也是非模态的。这个解决方法很简单,只要在Dispatcher里弹出这个MessageBox就可以了。

更多关于WPF Bug 

同系列的其它文章:

[WPF Bug清单]()与之(1)——可以多选的单选ListBox

[WPF Bug清单](2)——RadioButtonIsChecked绑定失效

[WPF Bug清单](3)——暗中创建文件的打开文件对话框

[WPF Bug清单](4)——点击RadioButton的空白没有反应

[WPF Bug清单](6)——ButtonIsCancel属性失效

[WPF Bug清单](7)——顽固的Error Template

[WPF Bug清单](8)——RowDefinitionMaxHeight在一定条件下失效

[WPF Bug清单](9)——消失的光标

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