5月份開發了臉萌WP版,其中須要使用web技術來繪製圖像,因而就使用了原生webbrowser控件。在使用webbrowser control的過程當中,發現了一些坑,也總結的幾個小技巧,分享給你們。javascript
首先咱們須要瞭解下webbrowser control,與桌面windows平臺上的webbrowser同樣,都是基於IE內核封裝的web展現控件,用法與wpf基本一致,同時也是非託管資源,但wp平臺上沒有實現IDispose接口,帶了了內存控制的挑戰。此外,webbrowser自己支持有限的js script和c#代碼交互,帶來了更多的可操做性。html
1.c#調用webbrowser functionhtml5
這裏主要是指使用本地代碼(C#)和webbrowser加載的Javascript代碼的交互行爲,利用此方法能夠很容易的實現web項目對wp原生項目的移植,這對web開發者來說是很方便的。這裏主要給你們介紹2個API:分別是InvokeScript()方法以及ScriptNotify事件。java
InvokeScript方法能夠傳參並執行webbrowser加載的javascript代碼中的函數,實現對應的效果,用法以下:web
webbrowser.InvokeScript("initPerson"); webbrowser.InvokeScript("initPerson", new string[] {"0","2001","1" });
第一段就是簡單的調用js function,第二行則是傳遞參數並調用js function。這兩種方法使用起來很靈活,足以來處理不少的交互行爲。以臉萌WP版爲例,我在C#中處理各類用戶行爲,並將得到的參數傳入webbrowser,js 腳本響應後會動態執行,使用web技術繪製出我想要的頭像,這很是靈活。json
同時,對js 函數適當的封裝能夠提升交互效率,由於InvokeScript可傳入的參數類型只能爲 string[],js函數不恰當的封裝會致使交互的困難,甚至是沒法交互,下面我舉例說明:c#
var personA = { 'eye': { 'id': 0 }, 'hair': { 'id': 0 } }; function initPerson(person) { a = person.eye.id; b = person.hair.id; }
這裏的initPerson函數須要直接傳入javascript對象,這是InvokeScript難以直接傳入的,但咱們能夠進行簡單的封裝,就能夠順利的實現意圖,以下:windows
var personA = { 'eye': { 'id': 0 }, 'hair': { 'id': 0 } }; function initPerson(person) { a = person.eye.id; b = person.hair.id; } function drawPerson(eyeId, hairId) { personA.eye.id = eyeId; personA.hair.id = hairId; initPerson(personA); }
這樣C#就直接能夠寫爲:架構
webbrowser.InvokeScript("drawPerson", new string[] {"0","2001" });
可以順利的實現交互,以上只是方法之一,你們還能夠直接傳入一個字符串,而後再在javascript中進行處理,以下:app
function initPerson(person) { if (typeof person == 'string') var person = eval(person); a = person.eye.id; b = person.hair.id; }
C#:
webbrowser.InvokeScript("initPerson", "{ 'eye': {'id': 0 }, 'hair': { 'id': 0}}");
藉助神奇的eval()函數,一樣能夠實現咱們想要的效果。MVP郝冠軍告訴我,使用eval並不恰當,可使用Native json API來替代,你們能夠自行搜索下用法,使用方式和eval一致。
2.webbrowser調用C#腳本
這裏使用的API主要是ScriptNotify事件,能夠實現javascript函數調用c#腳本的效果,可以動態的改變整個應用的行爲,這可以使得基於web技術的app調用更高級的原生功能,包括位置,推送,動態磁貼等等,是否是以爲很棒呀,下面咱們來看簡單的實現方式。
首先webbrowser須要註冊ScriptNotify事件,以接收來自javascript的信息
webbrowser.ScriptNotify += (e, g) => { //響應代碼 var result = g.Value; };
同時,javascript發送數據方式以下:
window.external.notify("參數");
如此便可實現webbrowser與整個app的動態交互,這是很是便利的。
3.webbrowser的內存控制
因爲webbrowser是非託管資源,同時wp上未實現IDispose接口,這給app的內存帶來了很大壓力,每次導航均可以明顯發現有20M左右內存沒有釋放,通過屢次檢查,發現是webbrowser的資源沒有釋放,同時也發現強制GC也沒有任何效果,最終通過一番學習,經過js來進行釋放,大幅減少了內存的消耗,但仍不完全,諸位大牛若是有好的辦法能夠指點下我。下面是個人方法:
js中將全部使用的資源都作空處理:
function memoryRelease() { personA = null; window = null; CollectGarbage(); }
C#每次在離開當前頁面時執行它:
protected override void OnNavigatedFrom(NavigationEventArgs e) { webbrowser.InvokeScript("memoryRelease"); }
CollectGarbage()是IE的一個特有屬性,用於釋放內存的,使用方法應該是,將該變量或引用對象,設置爲null或delete,而後在進行釋放動做。
經過這種方式能夠有效的減小內存泄漏,僅作拋磚引玉只用。
最後,silverlight架構下的webbrowser控件雖然坑很多,但還是一個很是靈活的控件,這對於使用html5開發跨平臺app的開發者來說,是個很是棒的方式。