.NET 6上的WebView2體驗

波多爾斯基發表於2022-04-27

上次說為了不想在web端登入部落格園,我想著還是繼續使用MarkWord編寫部落格,不過在使用的過程中,如果markdown檔案的目錄中有中文的話,Markdown預覽就不能夠顯示貼上的圖片了,原因是之前.NET Framework的WeBrowser庫太老了,應該升級一下。

替換WebBrowser的方案很多,在Stackoverflow上有人推薦使用WebView2,我就直接用了,也沒有多想,實際上使用的問題還是不少的,簡單記錄一下。

WebView2

這個東西是微軟推出基於Edge或者說是基於chromium核心的瀏覽器元件,可以提供現代的瀏覽器體驗,用於整合到.NET程式中,實現.NET對web的訪問與呼叫,或者反過來也行。這個東西感覺是CefSharp的有利競爭者呀,雖然我也沒咋用過CefSharp

WebBrowser->WebView2

遷移的第一步是引用的替換,WebBrowser在System.Windows.Forms.WebBrowser名稱空間,如果使用WPF的話,需要使用WindowsFormsHost,這個就體驗不是那麼好了,WPF下,有Microsoft.Web.WebView2.Wpf,可以提供給WPF原生的訪問,贊一個。

訪問DOM

然後就是出現的錯誤了,最難受的是,WebView2不提供對DOM的訪問許可權!,WebBrowser可以直接通過Document來訪問DOM節點,而WebView2只能設定訪問的Uri資訊,然後控制導航與呼叫js。

為了實現動態的控制預覽框的內容,訪問DOM是必須的,如果我動態的渲染一個檔案,然後隨時再構造Uri,再傳遞到WebView2中,那太囉嗦了。由於這個東西可以直接呼叫JS,那麼我們換一個思路:通過WebView2呼叫JS,然後使用Js操作DOM,曲線實現控制DOM的目標。廢話不多說,直接上程式碼。

if (winWebDoc.CoreWebView2 == null)
    return;
var script = "document.body.innerHTML = '" + Markdown.ToHtml(MarkValue, pipeline).Trim() + "'";
winWebDoc.ExecuteScriptAsync(script);

之前我也嘗試過document.write的方法,發現有點問題,還是不能正常識別。

WebView2除了直接在傳遞js的函式體以外,還可以呼叫頁面中的頂級JS函式,具體使用方法參見後面的參考文獻或者園子裡面的這篇文章,反正我這麼使用之後中文目錄的問題就解決了,不過右側渲染如果有回車換行的話,就經常會卡死,好像是引擎就崩潰了。

替換預設換行

經過debug,發現WebView2在執行的過程中,需要渲染的html內,標籤之間不能有\r\n之類的東西,如果有就寄了。而使用CommonMark.CommonMarkConverter.Convert方法轉換的markdown檔案都會有這個東西...

這個庫時間也比較久遠了,經過簡單研究,我換成了Markdig這個庫,二者相容,而且Markdig還提供了更多定製的地方,我這裡將所有的換行,替換為空字元。

 private MarkdownPipeline pipeline = new MarkdownPipelineBuilder()
                .ConfigureNewLine("")
                .Build();

這樣,換行就沒啥問題了,但是在初次使用時,會出現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的方式訪問。

結語

經過了一番折騰,終於是能夠繼續使用MarkWord寫部落格了,雖然我更換了主題之後,滾動不是很利索了,另外渲染程式碼換行好像還有點問題,不過好歹能用了,以後再折騰吧。

參考資料

非常詳細:https://weblog.west-wind.com/posts/2021/Jan/26/Chromium-WebView2-Control-and-NET-to-JavaScript-Interop-Part-2

相關文章