.NET 6 上的 WebView2 體驗
前言
上次說為了不想在web端登錄博客園,我想著還是繼續(xù)使用MarkWord編寫博客,不過在使用的過程中,如果markdown文件的目錄中有中文的話,Markdown預(yù)覽就不能夠顯示粘貼的圖片了,原因是之前.NET Framework的WeBrowser庫太老了,應(yīng)該升級一下。
替換WebBrowser的方案很多,在Stackoverflow上有人推薦使用WebView2,我就直接用了,也沒有多想,實際上使用的問題還是不少的,簡單記錄一下。
WebView2
這個東西是微軟推出基于Edge或者說是基于chromium內(nèi)核的瀏覽器組件,可以提供現(xiàn)代的瀏覽器體驗,用于集成到.NET程序中,實現(xiàn).NET對web的訪問與調(diào)用,或者反過來也行。這個東西感覺是CefSharp的有利競爭者呀,雖然我也沒咋用過CefSharp。
WebBrowser->WebView2
遷移的第一步是引用的替換,WebBrowser在System.Windows.Forms.WebBrowser命名空間,如果使用WPF的話,需要使用WindowsFormsHost,這個就體驗不是那么好了,WPF下,有Microsoft.Web.WebView2.Wpf,可以提供給WPF原生的訪問,贊一個。
訪問DOM
然后就是出現(xiàn)的錯誤了,最難受的是,WebView2不提供對DOM的訪問權(quán)限!,WebBrowser可以直接通過Document來訪問DOM節(jié)點,而WebView2只能設(shè)置訪問的Uri信息,然后控制導(dǎo)航與調(diào)用js。
為了實現(xiàn)動態(tài)的控制預(yù)覽框的內(nèi)容,訪問DOM是必須的,如果我動態(tài)的渲染一個文件,然后隨時再構(gòu)造Uri,再傳遞到WebView2中,那太啰嗦了。由于這個東西可以直接調(diào)用JS,那么我們換一個思路:通過WebView2調(diào)用JS,然后使用Js操作DOM,曲線實現(xiàn)控制DOM的目標(biāo)。廢話不多說,直接上代碼。
if?(winWebDoc.CoreWebView2?==?null)
????return;
var?script?=?"document.body.innerHTML?=?'"?+?Markdown.ToHtml(MarkValue,?pipeline).Trim()?+?"'";
winWebDoc.ExecuteScriptAsync(script);
之前我也嘗試過document.write的方法,發(fā)現(xiàn)有點問題,還是不能正常識別。
WebView2除了直接在傳遞js的函數(shù)體以外,還可以調(diào)用頁面中的頂級JS函數(shù),具體使用方法參見后面的參考文獻(xiàn)或者園子里面的這篇文章,反正我這么使用之后中文目錄的問題就解決了,不過右側(cè)渲染如果有回車換行的話,就經(jīng)常會卡死,好像是引擎就崩潰了。
替換默認(rèn)換行
經(jīng)過debug,發(fā)現(xiàn)WebView2在運(yùn)行的過程中,需要渲染的html內(nèi),標(biāo)簽之間不能有\(zhòng)r\n之類的東西,如果有就寄了。而使用CommonMark.CommonMarkConverter.Convert方法轉(zhuǎn)換的markdown文件都會有這個東西...
這個庫時間也比較久遠(yuǎn)了,經(jīng)過簡單研究,我換成了Markdig這個庫,二者兼容,而且Markdig還提供了更多定制的地方,我這里將所有的換行,替換為空字符。
?private?MarkdownPipeline?pipeline?=?new?MarkdownPipelineBuilder()
????????????????.ConfigureNewLine("")
????????????????.Build();
這樣,換行就沒啥問題了,但是在初次使用時,會出現(xiàn)WebView2無法正常渲染的問題。
WebView2初始化
WebView2的初始化和其他的庫有點不同,它提供了一個EnsureCoreWebView2Async的方法,對它的操作,請一定等這個方法返回。可以使用await,也可以和我一樣,使用TPL。
?winWebDoc.EnsureCoreWebView2Async()
????????????????????.ContinueWith(t?=>
????????????????{
????????????????????Dispatcher.Invoke(()?=>
????????????????????{
????????????????????????winWebDoc.Source?=?new?Uri(System.IO.Path.Combine(Environment.CurrentDirectory,?"index.html"));
????????????????????});
????????????????});
注意我這里使用加載了一個本地的模板HTML文件,訪問本地文件的時候,需要使用Uri的方式訪問。
結(jié)語
經(jīng)過了一番折騰,終于是能夠繼續(xù)使用MarkWord寫博客了,雖然我更換了主題之后,滾動不是很利索了,另外渲染代碼換行好像還有點問題,不過好歹能用了,以后再折騰吧。
P.S. WebView2可以通過更簡單的方法直接訪問網(wǎng)頁,使用
NavigateToString方法可以直接設(shè)置全局的document。
參考資料
非常詳細(xì):
https://weblog.west-wind.com/posts/2021/Jan/14/Taking-the-new-Chromium-WebView2-Control-for-a-Spin-in-NET-Part-1 https://weblog.west-wind.com/posts/2021/Jan/26/Chromium-WebView2-Control-and-NET-to-JavaScript-Interop-Part-2
轉(zhuǎn)自:波多爾斯基
鏈接:cnblogs.com/podolski/p/16199151.html
