轉(zhuǎn)帖|其它|編輯:郝浩|2011-04-08 15:08:23.000|閱讀 2828 次
概述:如何從WPF的WebBrowser控件中獲得WebResponse內(nèi)容?為何WebBrowser控件的Navigated事件參數(shù)NavigationEventArgs的WebResponse屬性始終為null?
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
問:
如何從WPF的WebBrowser控件中獲得WebResponse內(nèi)容?為何WebBrowser控件的Navigated事件參數(shù)NavigationEventArgs的WebResponse屬性始終為null?
我們在一個(gè)WPF的WebBrowser的Navigated事件中,嘗試去輸出NavigationEventArgs e的WebResponse屬性,他始終是null。比如,
XAML代碼:
<WebBrowser x:Name="browser"/>
C#代碼:
browser.Navigated += new NavigatedEventHandler(browser_Navigated);
browser.Navigate(new Uri("//www.microsoft.com"));
//省略...
void browser_Navigated(object sender, NavigationEventArgs e)
{
Console.WriteLine(e.WebResponse.Headers); //輸出null
}
[相關(guān)MSDN英文貼://social.msdn.microsoft.com/Forums/en-US/wpf/thread/856608db-48ba-4492-bff1-3721618ff3ae]
答:
一般都會(huì)認(rèn)為從WebBrowser中獲得WebResponse內(nèi)容,可以從Navigated事件的NavigationEventArgs參數(shù)中獲得。但是,事實(shí)是這個(gè)參數(shù)始終在返回null值,導(dǎo)致無法真正獲得返回的內(nèi)容。
解決這個(gè)問題,首先想到的是去了解WebBrowser控件的基本組成。我們知道,IE的結(jié)構(gòu)是如下:
而對于一個(gè)WebBrowser控件(無論是Winform的還是WPF的),都是和這個(gè)架構(gòu)類似的,不同的只是最上層的UI封裝。控件來說,是沒有IExplore.exe的包裝的,所以一般控件就沒有IE的某些特性,但是從底層來說,他們都使用了ShDocVw.dll和MSHTML.dll,控件只是對下方組件的一次封裝。那么這個(gè)Navigated事件是從誰拋出的呢?答案是ShDocVw.dll,當(dāng)然,面向不同的封裝,拋到上方會(huì)遇到不同的處理。Wnform中的WebBrowserNavigatedEventArgs中沒有封裝WebResponse信息,而從WPF的WebBrowser中,卻包含了這個(gè)屬性。
接下來,從表象很難找到原因了,這個(gè)時(shí)候就需要借助下工具,比如我使用了Reflector (從這里可以下載到試用版://reflector.red-gate.com/download.aspx?TreatAsUpdate=1)去反編譯了一些源代碼,嘗試去分析下為什么會(huì)一直返回null。通過工具分析,我們可以找到下面的一個(gè)調(diào)用列表:
在NavigationEventArgs類中的_webResponse成員實(shí)際就是我們要分析的對象,他僅由NavigationEventArgs的構(gòu)造函數(shù)調(diào)用。而從他的構(gòu)造函數(shù)的被調(diào)用列表中,我們發(fā)現(xiàn)了兩類方法,一類是被定義在MS.Internal.Controls.WebBrowserEvent中的,還有是定義在System.Windows.Navigation.NavigationService中的。當(dāng)然,我們可以想到,第一類是所謂WebBrowser控件的內(nèi)部組件類,這個(gè)類實(shí)際就是所謂架構(gòu)中對于ShDocVw.dll的一次.Net封裝。所以這個(gè)類的方法就是WebBrowser在Navigated的時(shí)候調(diào)用的。點(diǎn)擊顯示MS.Internal.Controls.WebBrowserEvent.NavigateComplete2方法的邏輯代碼:
[SecurityTreatAsSafe, SecurityCritical]
public void NavigateComplete2(object pDisp, ref object url)
{
//省略…
NavigationEventArgs e = new NavigationEventArgs(uri, null, null, null, null, true);
this._parent.OnNavigated(e);
//省略…
}
可以看出,代碼中直接使用null值構(gòu)造了NavigationEventArgs參數(shù),然后觸發(fā)WebBrowser.Navigated事件。(當(dāng)然,你也可以看DocumentComplete方法,在這個(gè)里面一樣的用了null去構(gòu)造后觸發(fā)了WebBrowser.LoadCompleted事件)
到此可以解釋為什么WebResponse屬性總是返回null了。
等等,還沒有結(jié)束。那么怎么去獲得WebBrowser呢? 我們還省略沒有去看另外的幾個(gè)NavigationService的方法,比如System.Windows.Navigation.NavigationService.FireNavigated方法邏輯代碼:
private void FireNavigated(object navState)
{
object extraData = (navState is NavigateInfo) ? null : navState;
try
{
NavigationEventArgs e = new NavigationEventArgs
(this.CurrentSource, this.Content, extraData, this._webResponse,
this.INavigatorHost, this.IsNavigationInitiator);
//省略…
}
可以看出,NavigationService在他的事件中封裝了WebResponse信息。這樣的話,就有了解決方案——
使用NavigationService去Navigate頁面,并且在Navigated事件中獲得。但是WebBrowser本身沒有支持NavigationService,在WPF中只有NavigationWindow和Frame支持了NavigationService,所以我們只需要使用這兩者,這里我的代碼是用了Frame替代了WebBrowser,
XAML:
<Frame x:Name="frame"/>
C#代碼:
frame.Navigated += new NavigatedEventHandler(frame_Navigated);
frame.NavigationService.Navigate(new Uri("//www.microsoft.com"));
//省略...
void frame_Navigated(object sender, NavigationEventArgs e)
{
Console.WriteLine(e.WebResponse.Headers);
}
[備注:]在WebBrowser和Frame之間,我的第一感覺是,如果你需要一個(gè)瀏覽控件有依賴屬性來支持綁定等WPF特性的話,那么就選擇Frame吧,它包含你所需要的依賴屬性,而WebBrowser沒有。 不過我還會(huì)推薦下一個(gè)第三方的WPF瀏覽器控件://wpfchromium.codeplex.com/ 基于Google的Chromium項(xiàng)目的。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn