2009/12/31

WPF Frame.NavigationFailed 正確捕捉方式

我們的程式用到了 Frame 當作瀏覽器視窗,可以接受使用者輸入的 URL 顯示網頁。但如果使用者隨便輸入或鍵入一個不存在的網址要求 (使用 frame.Navigate(Uri)),Frame 會跳出 WebException。

因為這樣會強制結束程式,所以我加個 try ... catch 來攔截,這下總沒有問題了吧?

try{
    frame.Navigate(new Uri(url));
}catch{
    // show something ...
}

結果程式一跑,相同的 Exception 一樣憑空跳出,讓我丈二金剛摸不著頭腦,究竟是怎麼一回事呢?查了MSDN發現,原來 Frame 有專屬的 NavigationFailed 事件,要撰寫事件來抓這個錯誤才行,Navigate 方法本身不丟出錯誤的。

frmBrowser.NavigationFailed += new NavigationFailedEventHandler(this.NavigationFailedEventHandler);

private void NavigationFailedEventHandler(object sender, NavigationFailedEventArgs e) {
    // show something ...
}

好,我按照 MSDN 的說明,用了事件捕捉,這下總沒事了吧?事情通常沒我們想的簡單,Exception 還是偷偷的跑出來打斷了我們的程式,怎麼會這樣?

注意看 MSDN,尋找可能的問題,後來發現事件的其中一個參數 NavigationFailedEventArgs 非常可疑,一看才知道原來它隱藏著本篇的解藥!其實就是它的 Handled 屬性。說明是這樣寫的:
當處理 NavigationFailed 以處理因巡覽失敗所擲回的例外狀況,而您也不想 WPF 繼續處理例外狀況時,應該將 Handled 屬性設定為 true。
private void NavigationFailedEventHandler(object sender, NavigationFailedEventArgs e) {
    // show something ...
    e.Handled = true; // 已處理,不再擲出錯誤
}

結果加了一行,例外就乖乖的不出現了。如此重要的參數竟然在事件裡或範例中隻字未提,如果沒有發現 NavigationFailedEventArgs 參數的玄機,我想會卡非常久。特此將此經驗公諸於世,希望能救到後來人。

1 則留言:

  1. 一針見血
    這應該是不少人在用Frame當瀏覽器時,會遇到的問題吧
    感謝您

    回覆刪除