發現這個問題時,隱約記得之前有人已經發過這個問題,想把鏈接放到這里,不過找了半天,實在找不到。日后如果找到了一定加上。
問題描述:用方法彈出一個模態對話框,然后將此對話框的屬性設置為,再設置回,發現這個對話框已經不是模態的了。
有人會覺得關就關了得了,也不會有這個問題,干什么要把Close取消掉然后再顯示出來呢?因為這是有應用環境的。
應用環境:有些對話框模態對話框是什么時候實例的對話框,從邏輯上就是單例的,比如和 里都有的查找對話框,顯然沒有必要同時顯示兩個。而且也沒有必要每次重新實例化并顯示出來,在用戶關閉窗體時,將窗體隱藏起來會更好,這樣上次查找的關鍵字還存在著??梢允∪ヒ恍┐a保存這個歷史關鍵字。
當然,這種方式也會有不好的地方,歡迎大家指摘。
寫了一個程序來模擬這個Bug模態對話框是什么時候實例的對話框,效果如下面三張圖所示。
圖1. 主窗體,點第一個按鈕
圖2. 彈出的模態對話框,點擊按鈕將自己隱藏
圖3. 再點擊主窗體的最后一個按鈕,顯示出來,已經是非模態對話框了
以前發Bug,一般沒有去看過.NET的源代碼,這次感覺這個Bug 有點兒太不應該了,就看了看源代碼,發現WPF還特意為(模態的)的做了單獨的處理,感覺就更不應該有問題了,我們來看看源代碼。
[,]
ide()
{
.();
=false;
if(this.!=null)
{
this..=false;
this.=null;
}
if(!this..)
{
this.=false;
}
this.=false;//
=this._swh.;
this.(true);
if((&&(this.!=.Zero))&&.((this,this.)))
{
.((this,this.));
}
}
其中直接把設置為了false,當再次把窗體的設置為的時候,類又會根據這個變量的值來判斷是否將窗體按模態的方式顯示出來。而MS對這行代碼的的注釋僅僅是“// ”。
從源代碼上來看,WPF的似乎是使用下面的代碼將一個窗體從非模態變成模態的。
try
{
//'
.();
=();
.();
}
{
//'-modal
.();
}
但是當我自己在使用里使用這個方法的時候,卻發現根本達不到目的。后來突然想到一個方法,試了一下,就可以。解決方法是,不使用 = ,使窗體再次顯示出來。而且再調用一次方法來顯示這個窗體。這個方法也許只有對WPF不熟悉或是非常熟悉的人才能想得出來(我是死馬當作活馬醫碰對了),因為正常情況下,繼續地第二次調用方法是會拋出異常的。類似的詭異的的異常在[WPF]如何在關閉非模態子窗體時用消息框確認——解決最小化窗體時拋出的異常里也有描述。
另外,在非UI線程彈出的也是非模態的。這個解決方法很簡單,只要在里彈出這個就可以了。
更多關于WPF Bug
同系列的其它文章:
[WPF Bug清單](序)與之(1)——可以多選的單選
[WPF Bug清單]之(2)——的綁定失效
[WPF Bug清單]之(3)——暗中創建文件的打開文件對話框
[WPF Bug清單]之(4)——點擊的空白沒有反應
[WPF Bug清單]之(6)——的屬性失效
[WPF Bug清單]之(7)——頑固的Error
[WPF Bug清單]之(8)——中在一定條件下失效
[WPF Bug清單]之(9)——消失的光標