【问题标题】:Equivalent of WebBrowser.InvokeScript(String, Object[]) in WebView2等效于 WebView2 中的 WebBrowser.InvokeScript(String, Object[])
【发布时间】:2020-10-31 06:28:28
【问题描述】:

提前致谢。

在我的 WPF 应用程序中,我能够使用 WebBrowser 的 InvokeScript(String, Object[]) 方法成功地将消息从 WPF 传递到 JavaScript。我在 Object[] 参数中传递我的消息,JS 代码很好地接受了它。 (见下面的代码)

如何在 WebView2 中实现相同的功能,有什么方法可以像在 WebBrowser 控件中一样将参数传递给 JS 代码?

Window.xaml

 <Grid>
            <DockPanel> 
                <StackPanel>        
                <TextBox x:Name="txtMessageFromWPF" Width="150" FontSize="20"></TextBox>
                <Button x:Name="btnCallDocument" Click="btnCallDocument_Click" Content="CallDocument" />
                </StackPanel>
                <WebBrowser x:Name="webBrowser" DockPanel.Dock="Top" Margin="30"/>           
            </DockPanel>
        </Grid>

Window.xaml.cs

        private void btnCallDocument_Click(object sender, RoutedEventArgs e)
        {
            webBrowser.InvokeScript("WriteMessageFromWPF", new object[] { this.txtMessageFromWPF.Text });
        }

JS代码:

 <script type="text/javascript">
            function getAlert()
            {
                alert("Hi the page is loaded!!!");
            }
            window.onload = getAlert;
            
            function WriteMessageFromWPF(message){
                document.write("Message from WPF: " + message);
            }
        </script>

【问题讨论】:

    标签: .net webview webbrowser-control webview2


    【解决方案1】:

    目前在 WebView2 中没有直接等效的 InvokeScript。最接近的是CoreWebView2.ExecuteScriptAsync。此方法需要一个脚本字符串来运行,并以 JSON 字符串的形式异步返回脚本执行的结果。

    如果您想调用一个函数,您需要创建一个脚本字符串来执行此操作并将其提供给 ExecuteScriptAsync。在您的示例中,这意味着生成字符串 WriteMessageFromWPF("...") 并将其提供给 ExecuteScriptAsync。

    棘手的部分是正确编码您的函数参数。如果字符串参数中有引号,那么您需要斜杠转义引号,否则会产生不正确的脚本。您应该能够使用 String.Replace 对引号进行斜线转义:

    string script = "WriteMessageFromWPF(\"" + 
        this.txtMessageFromWPF.Text.Replace("\"", "\\\"")
        + "\")";
    await webview2.CoreWebView2.ExecuteScriptAsync(script);
    

    【讨论】:

    • 我在here 发布了类似的场景,以防有人有任何建议/cmets。
    【解决方案2】:

    更新:扩展的第 2 版更简单、更通用。它使用 JSON 作为“中间站”——使用 NewtonSoft 或内置的 JSON 转换器。

    这是我制作的扩展(只需创建一个类文件并粘贴即可)。

    ExecuteScriptFunctionAsync 构建ExecuteScriptAsync 所需的字符串,然后执行它:

    //using Microsoft.Web.WebView2.WinForms; //Uncomment the one you use
    //using Microsoft.Web.WebView2.Wpf; //Uncomment the one you use
    using Newtonsoft.Json;
    using System.Threading.Tasks;
    
    public static class Extensions
    {
        public static async Task<string> ExecuteScriptFunctionAsync(this WebView2 webView2, string functionName, params object[] parameters)
        {
            string script = functionName + "(";
            for (int i = 0; i < parameters.Length; i++)
            {
                script += JsonConvert.SerializeObject(parameters[i]);
                if (i < parameters.Length - 1)
                {
                    script += ", ";
                }
            }
            script += ");";
            return await webView2.ExecuteScriptAsync(script);
        }
    }
    

    将 javascript 函数名作为第一个参数传递,然后是函数参数。

    该代码可以将任意数量的所有类型的参数序列化为 JSON:objectarraystringall numbersboolean 等。

    使用示例(来自问题):

    private async void btnCallDocument_Click(object sender, RoutedEventArgs e)
    {
        await webBrowser.ExecuteScriptFunctionAsync("WriteMessageFromWPF", this.txtMessageFromWPF.Text);
    }
    

    另一个例子(这会将窗口滚动到底部):

    await webView21.ExecuteScriptFunctionAsync("window.scrollTo", 0, 10000);
    

    【讨论】:

    • 您的扩展程序(或类似的东西)是否适用于 WinUI 3.0UWP 中的内置 WebView2 - 例如在 this 场景中?
    • @nam:我对WinUI一无所知,建议你试试。您需要找到 WinUI WebView2 的“使用”指令
    • 请记住,它确实会尝试将所有内容都转换为 JSON,即使您只返回一个字符串。它将用引号括起来,而 javascript 将其转义。
    • 确实如此。当 'ExecuteScriptAsync ' 返回时,您将始终拥有一个必须反序列化的 JSON 字符串。 “WebMessageReceived”也是如此。
    • 你会如何把它传回 JS?
    猜你喜欢
    • 2021-01-14
    • 2020-10-07
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多