哪个 WebView2 事件/函数可用于替换 ScriptNotify Webview 事件? [英] Which WebView2 event/function can be use to replace ScriptNotify Webview event?

查看:45
本文介绍了哪个 WebView2 事件/函数可用于替换 ScriptNotify Webview 事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天,我决定将 WebView 控件迁移到 VB.net 应用程序中的 WebView2 控件.

我已经从 NuGet 安装了 WebView2 并且更改了声明和初始化行(在我的 VB 程序中只有 4 行,因为我使用的是 2 个 WebView2).

当我构建应用程序时,Visual Studio 2019 指示 ScriptNotify 事件不是 WebView2 的事件!

私有子 wvSelect_ScriptNotify(发送者作为对象,e 作为 WebViewControlScriptNotifyEventArgs) 处理 wvSelect.ScriptNotify

使用旧的 WebView 控件,此事件是使用 windows.external.notify Javascript 函数生成的.

function clickPlus(e) { window.external.notify("+PLUS:");}

哪个事件正在替换 WebView2 控件中的 ScriptNotify 事件?

我有兴趣了解新事件以及如何从 Javascript 调用此事件.

解决方案

使用 WebView2:
另请参阅:在 WebView 中使用 JavaScript 进行扩展方案.

通用初始化:


Private Async Sub Load(sender As Object, e as EventArgs) 处理 MyBase.Load等待 myWebView2.EnsureCoreWebView2Async(Nothing)结束子

此外,我正在使用这个简单的类模型,用于反序列化收到的 JSON 消息,因为 WebView2.WebMessageReceived 采用 JSON 格式;不过,你可以传递任何你想要的字符串.

私有类JsonEventMessage公共属性元素作为字符串公共属性值作为字符串结束类


1 - 在这种情况下,javascript 函数已经在 HTML 中定义

<头><script type="text/javascript">函数 SomeFunction(e, v) {var json = JSON.stringify({ 元素:e.target.id, 值:v });window.chrome.webview.postMessage(json);}<身体><脚本>document.getElementById("div1").addEventListener("click", function(e) {SomeFunction(e, '+PLUS:')});<div id="div1">要点击的一些文本</div></html>

在这种情况下,您只需要订阅 WebMessageReceived 事件并反序列化 JSON(如果您传递了 JSON 对象):

AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived' [...]Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)Dim message = New JavaScriptSerializer().Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())Console.WriteLine(message.Element)Console.WriteLine(message.Value)结束子

注意:我正在使用 e.TryGetWebMessageAsString() 而不是 e.WebMessageAsJson 因为后者用引号括起来(双字符串化).当你传递一个简单的字符串时,它会更好地使用.


2 - 这里,在HEAD中定义了一个可以通知消息的javascript函数,但没有在其他任何地方添加事件处理程序.
假设您将在运行时添加 HTML 元素,或者您不想在 HTML 或其他任何内容中添加事件处理程序.

<头><script type="text/javascript">函数 SomeFunction(e, v) {var json = JSON.stringify({ 元素:e.target.id, 值:v });window.chrome.webview.postMessage(json);}<身体><div id="div1">要点击的一些文本</div></html>

像以前一样订阅 WebMessageReceived 事件和 NavigationCompleted 事件.加载文档时引发此事件.我们需要这个事件,因为在这个例子中,事件处理程序被添加到 Body 中的 Elements 中,这在这之前是不可用的.

NavigationCompleted中,我们可以将javascript函数添加到字符串中并调用WebView2.ExecuteScriptAsync() 方法,在 DOM 准备好后执行脚本,否则 GetElementById() 会找不到目标.

AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceivedAddHandler myWebView2.NavigationCompleted, AddressOf myWebView2_NavigationCompleted' [...]Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)Dim message = New JavaScriptSerializer().Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())' [...]结束子Private Async Sub myWebView2_NavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs)Dim func As String ="document.getElementById('div1').addEventListener('click', function(e) {SomeFunction(e, '+PLUS:')});"等待 myWebView2.ExecuteScriptAsync(func)结束子


3 - 这一次,HTML 中的任何地方都没有定义 javascript 函数.

<头><身体><div id="div1">要点击的一些文本</div></html>

案例 1:
像以前一样订阅 WebMessageReceivedNavigationCompleted 事件.

NavigationCompleted中,将发布消息的javascript函数直接添加到事件处理程序中.调用 ExecuteScriptAsync() 以执行脚本并将事件侦听器添加到 HTML 元素.

AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceivedAddHandler myWebView2.NavigationCompleted, AddressOf myWebView2_NavigationCompleted' [...]Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)Dim message = New JavaScriptSerializer().Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())' [...]结束子Private Async Sub myWebView2_NavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs)Dim func As String ="document.getElementById('div1').addEventListener('click', function(e) {var json = JSON.stringify({Element:e.target.id, Value:'+PLUS:'});window.chrome.webview.postMessage(json);});"等待 myWebView2.ExecuteScriptAsync(func)结束子

案例 2:
订阅 WebMessageReceivedWebView2.CoreWebView2InitializationCompleted.
在本例中,我们向 Document 添加了一个事件侦听器,然后使用 Event.Target 成员和任何其他可用于处理通知的属性或值来确定已单击哪个元素.

在这里,我只是将 [Event].target.id[Event].target.innerText 作为 JSON 属性传递.您当然可以在您的用例中获得任何其他必要的属性.

AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceivedAddHandler myWebView2.CoreWebView2InitializationCompleted, AddressOf myWebView2_CoreWebView2InitializationCompleted' [...]Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)Dim message = New JavaScriptSerializer().反序列化(JsonEventMessage)(e.TryGetWebMessageAsString())' [...]结束子私有异步子 myWebView2_CoreWebView2InitializationCompleted(发送者作为对象,e 作为 CoreWebView2InitializationCompletedEventArgs)Dim func as String ="document.addEventListener('点击',功能(e){window.chrome.webview.postMessage(JSON.stringify({元素:e.target.id,值:e.target.innerText}));});"等待 myWebView2.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(func)结束子

Today, I have decided to migrate WebView control to WebView2 control in a VB.net application.

I have installed WebView2 from NuGet and I have changed declarations and initialization lines (only 4 lines in my VB program because I'm using 2 WebView2).

When I build my application, Visual Studio 2019 indicates that ScriptNotify event is not an event of WebView2!

Private Sub wvSelect_ScriptNotify(
    sender As Object, 
    e As WebViewControlScriptNotifyEventArgs) Handles wvSelect.ScriptNotify

Using old WebView control, this event is generated using windows.external.notify Javascript function.

function clickPlus(e) { window.external.notify("+PLUS:"); }

Which event is replacing ScriptNotify event in WebView2 control?

I'm interested to know the new event and also how this event is called from Javascript.

解决方案

A few possible scenarios to handle event notifications with WebView2:
See also: Use JavaScript in WebView for extended scenarios.

Generic initialization:

  • The WebView2 instance is named myWebView2.
  • Also assuming WinForms, you haven't specified the GUI framework

Private Async Sub Load(sender As Object, e as EventArgs) Handles MyBase.Load
    await myWebView2.EnsureCoreWebView2Async(Nothing)
End Sub

Also, I'm using this simple class model, used to deserialize the JSON message received, since WebView2.WebMessageReceived assumes a JSON format; you can pass whatever string you want, though.

Private Class JsonEventMessage
    Public Property Element As String
    Public Property Value As String
End Class


1 - In this scenario, javascript Functions are already defined in the HTML

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript">
        function SomeFunction(e, v) {
           var json = JSON.stringify({ Element:e.target.id, Value:v });
           window.chrome.webview.postMessage(json);
        }
    </script>
</head>
<body>
    <script>
        document.getElementById("div1").addEventListener("click", function(e) {SomeFunction(e, '+PLUS:')});
    </script>
    <div id="div1">Some Text to Click</div>
</body>
</html>

In this case, you just need to subscribe to the WebMessageReceived event and deserialize the JSON (if you passed a JSON object):

AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived

' [...]

Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
    Dim message = New JavaScriptSerializer().Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())
    Console.WriteLine(message.Element)
    Console.WriteLine(message.Value)
End Sub

Note: I'm using e.TryGetWebMessageAsString() and not e.WebMessageAsJson since the latter is enclosed in quotes (double-stringified). It's better used when you pass a simple string.


2 - Here, a javascript Function that can notify a message is defined in HEAD, but no event handlers are added anywhere else.
Assume you will add HTML Elements at run-time or you don't want to add the event handlers in the HTML or anything else.

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript">
        function SomeFunction(e, v) {
           var json = JSON.stringify({ Element:e.target.id, Value:v });
           window.chrome.webview.postMessage(json);
        }
    </script>
</head>
<body>
    <div id="div1">Some Text to Click</div>
</body>
</html>

Subscribe to the WebMessageReceived event as before and to the NavigationCompleted event. This event is raised when the Document is loaded. We need this event, since, in the example, the event handlers are added to Elements in the Body, which is not available before this point.

In NavigationCompleted, we can add the javascript Function to a string and call the WebView2.ExecuteScriptAsync() method, which executes the script after the DOM is ready, otherwise GetElementById() would not find the target.

AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived
AddHandler myWebView2.NavigationCompleted, AddressOf myWebView2_NavigationCompleted

' [...]

Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
    Dim message = New JavaScriptSerializer().Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())
    ' [...]
End Sub

Private Async Sub myWebView2_NavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs)
    Dim func As String =
        "document.getElementById('div1').
            addEventListener('click', function(e) { 
                SomeFunction(e, '+PLUS:')
            });"
    Await myWebView2.ExecuteScriptAsync(func)
End Sub


3 - This time, no javascript Functions are defined anywhere in the HTML.

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <div id="div1">Some Text to Click</div>
</body>
</html>

Case 1:
Subscribe to the WebMessageReceived and NavigationCompleted events as before.

In NavigationCompleted, the javascript Function that post the message is added to the event handler directly. Call the ExecuteScriptAsync() to execute the script and add the Event Listener to a HTML Element.

AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived
AddHandler myWebView2.NavigationCompleted, AddressOf myWebView2_NavigationCompleted

' [...]

Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
    Dim message = New JavaScriptSerializer().Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())
    ' [...]
End Sub

Private Async Sub myWebView2_NavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs)
    Dim func As String =
    "document.getElementById('div1').
        addEventListener('click', function(e) { 
            var json = JSON.stringify({Element:e.target.id, Value:'+PLUS:'});
            window.chrome.webview.postMessage(json); 
    });"
    Await myWebView2.ExecuteScriptAsync(func)
End Sub

Case 2:
Subscribe to the WebMessageReceived and WebView2.CoreWebView2InitializationCompleted.
In this case, we're adding an event listener to the Document, then determine which Element has been clicked using the Event.Target member and any other property or value that can be useful to handle the notification.

Here, I'm simply passing the [Event].target.id and [Event].target.innerText as JSON properties. You of course can get any other attribute necessary in your use-case.

AddHandler myWebView2.WebMessageReceived, AddressOf myWebView2_WebMessageReceived
AddHandler myWebView2.CoreWebView2InitializationCompleted, AddressOf myWebView2_CoreWebView2InitializationCompleted
' [...]

Private Sub myWebView2_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs)
    Dim message = New JavaScriptSerializer().
        Deserialize(Of JsonEventMessage)(e.TryGetWebMessageAsString())
    ' [...]
End Sub

Private Async Sub myWebView2_CoreWebView2InitializationCompleted(
    sender As Object, 
    e As CoreWebView2InitializationCompletedEventArgs)

    Dim func as String = 
    "document.addEventListener
        ('click', function(e) {
            window.chrome.webview.postMessage(
                JSON.stringify({ 
                    Element:e.target.id, 
                    Value:e.target.innerText
                })
            );
       });"
    Await myWebView2.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(func)
End Sub

这篇关于哪个 WebView2 事件/函数可用于替换 ScriptNotify Webview 事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆