C# 使用WebView2-Edge创建选项卡

C# 使用WebView2-Edge创建选项卡,c#,microsoft-edge,winforms-to-web,webview2,C#,Microsoft Edge,Winforms To Web,Webview2,请提供代码片段,以便在单击webview2-Edge in C#windows窗体中的链接时创建选项卡,而不是在新窗口中打开页面 遵循以下步骤 在C#windows窗体上拖动webview2控件并更新源属性链接: 网站已在webview2中成功打开 单击站点中的几个链接,它会打开新窗口,并在“新”选项卡中查找“打开此链接”,而不是在“新窗口”中打开它 调试代码时,此事件webView.CoreWebView2.NewWindowRequested从未命中。如果引发此webView.Core

请提供代码片段,以便在单击webview2-Edge in C#windows窗体中的链接时创建选项卡,而不是在新窗口中打开页面

遵循以下步骤

  • 在C#windows窗体上拖动webview2控件并更新源属性链接:

  • 网站已在webview2中成功打开

  • 单击站点中的几个链接,它会打开新窗口,并在“新”选项卡中查找“打开此链接”,而不是在“新窗口”中打开它

  • 调试代码时,此事件webView.CoreWebView2.NewWindowRequested从未命中。如果引发此webView.CoreWebView2.NewWindowRequested事件,则webView类上没有可用的导航方法,CoreWebView2类上也没有可用的导航方法,如果使用此方法,则会获得空引用异常


  • WebView2中没有对选项卡的内置支持。但是,您可以使用NewWindowRequested事件截取新窗口,并提供自己的CoreWebView2作为新窗口,然后将CoreWebView2以您喜欢的方式放置在UI中。例如,可以将新的CoreWebView2放在UI中,使其看起来像一个新选项卡。(听起来你就是这么做的,但在这里明确声明它只是为了确保我正确理解你的场景。)

    关于null WebView2.CoreWebView2属性,您可以调用并等待返回的任务,也可以设置WebView2.Source属性并等待分派,以便填写WebView2.CoreWebView2属性。在此之前为空

    此外,如果需要获取CoreWebView2来填写,因为从WebView2实例获取CoreWebView2的上述步骤都是异步的,在NewWindowRequested事件处理程序中启动异步工作之前,需要调用,在NewWindowRequested事件处理程序中完成异步工作后,需要在延迟上调用Complete


    如果您发现WebView2正在打开新窗口,但NewWindowRequested事件未触发,请打开错误。您在WebView2中使用的SDK和浏览器版本是什么?现在,有些场景打开新窗口时没有触发NewWindowRequested事件,存在一些已修复的错误。

    WebView2中没有内置的选项卡支持。但是,您可以使用NewWindowRequested事件截取新窗口,并提供自己的CoreWebView2作为新窗口,然后将CoreWebView2以您喜欢的方式放置在UI中。例如,可以将新的CoreWebView2放在UI中,使其看起来像一个新选项卡。(听起来你就是这么做的,但在这里明确声明它只是为了确保我正确理解你的场景。)

    关于null WebView2.CoreWebView2属性,您可以调用并等待返回的任务,也可以设置WebView2.Source属性并等待分派,以便填写WebView2.CoreWebView2属性。在此之前为空

    此外,如果需要获取CoreWebView2来填写,因为从WebView2实例获取CoreWebView2的上述步骤都是异步的,在NewWindowRequested事件处理程序中启动异步工作之前,需要调用,在NewWindowRequested事件处理程序中完成异步工作后,需要在延迟上调用Complete


    如果您发现WebView2正在打开新窗口,但NewWindowRequested事件未触发,请打开错误。您在WebView2中使用的SDK和浏览器版本是什么?现在已经修复了一些错误,其中一些场景打开新窗口时没有触发NewWindowRequested事件。

    为了完整起见,由于David Risney的解释,我能够实现同样的效果。不幸的是,它没有包含任何代码,但我使用
    1.0.721-prerelease
    Microsoft.WebView2.FixedVersionRuntime.87.0.664.66.x64
    实现了这一点:

    Program.cs:

    using System;
    using System.Windows.Forms;
    
    namespace TestApp1
    {
        static class Program
        {
            public static Microsoft.Web.WebView2.Core.CoreWebView2Environment WebView2Environment;
    
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }
    }
    
    表格1.cs:

    using System;
    using System.Windows.Forms;
    
    namespace TestApp1
    {
        public partial class Form1 : Form
        {
            public Microsoft.Web.WebView2.Core.CoreWebView2Deferral Deferral;
            public Microsoft.Web.WebView2.Core.CoreWebView2NewWindowRequestedEventArgs Args;
    
            public Form1()
            {
                InitializeComponent();
                webView21.CoreWebView2InitializationCompleted += webView21_CoreWebView2InitializationCompleted_1;
            }
    
            private void CoreWebView2_NewWindowRequested(object sender, Microsoft.Web.WebView2.Core.CoreWebView2NewWindowRequestedEventArgs e)
            {
                Form1 f = new Form1();
                f.Args = e;
                f.Deferral = e.GetDeferral();
                f.Show();
            }
    
            private async void Form1_Load(object sender, EventArgs e)
            {
                if (Program.WebView2Environment == null)
                    Program.WebView2Environment = Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(@"C:\Users\Dragon\Downloads\Microsoft.WebView2.FixedVersionRuntime.87.0.664.66.x64", $@"C:\Users\Dragon\Desktop\Test{Guid.NewGuid()}").Result;
                await webView21.EnsureCoreWebView2Async(Program.WebView2Environment);
                webView21.Source = new Uri("http://www.google.com");
            }
    
            private void webView21_CoreWebView2InitializationCompleted_1(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
            {
                if (!e.IsSuccess) { MessageBox.Show($"{e.InitializationException}"); }
    
                if (Deferral != null)
                {
                    Args.NewWindow = webView21.CoreWebView2;
                    Deferral.Complete();
                }
    
                webView21.CoreWebView2.NewWindowRequested += CoreWebView2_NewWindowRequested;
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                webView21.ExecuteScriptAsync($@"window.open('http://www.bing.com', '_blank');");
            }
        }
    }
    
    所以这种工作方式有点奇怪:要生成一个新窗口,可以使用
    ExecuteScriptAsync
    通过JavaScript来实现。在这种情况下,我将打开bing.com的一个新窗口。因此,这将调用
    CoreWebView2\u NewWindowRequested
    。要使事件通过,代码工作(否则它将冻结),它必须经历所有过程。因此,无法在当前发生的事件中设置
    CoreWebView2NewWindowRequestedEventArgs
    NewWindow
    属性

    解决方案是将事件数据(args和deleral)带到新表单中,显示它,并在加载时和之后调用
    CoreWebView2InitializationCompleted
    ,控件的
    CoreWebView2
    属性不为空/已初始化,检查args/deferral是否不为null,然后将defer调用为
    Complete()
    (这基本上类似于JS promise)在这里,您可以将
    NewWindow
    属性设置为
    CoreWebView2
    已初始化,因此它不为null


    希望这能回答你的问题和未来的读者。有了这段代码,我就能够让它工作。

    为了完整起见,多亏了David Risney的解释,我才能实现同样的目标。不幸的是,它没有包含任何代码,但我使用
    1.0.721-prerelease
    Microsoft.WebView2.FixedVersionRuntime.87.0.664.66.x64
    实现了这一点:

    Program.cs:

    using System;
    using System.Windows.Forms;
    
    namespace TestApp1
    {
        static class Program
        {
            public static Microsoft.Web.WebView2.Core.CoreWebView2Environment WebView2Environment;
    
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }
    }
    
    表格1.cs:

    using System;
    using System.Windows.Forms;
    
    namespace TestApp1
    {
        public partial class Form1 : Form
        {
            public Microsoft.Web.WebView2.Core.CoreWebView2Deferral Deferral;
            public Microsoft.Web.WebView2.Core.CoreWebView2NewWindowRequestedEventArgs Args;
    
            public Form1()
            {
                InitializeComponent();
                webView21.CoreWebView2InitializationCompleted += webView21_CoreWebView2InitializationCompleted_1;
            }
    
            private void CoreWebView2_NewWindowRequested(object sender, Microsoft.Web.WebView2.Core.CoreWebView2NewWindowRequestedEventArgs e)
            {
                Form1 f = new Form1();
                f.Args = e;
                f.Deferral = e.GetDeferral();
                f.Show();
            }
    
            private async void Form1_Load(object sender, EventArgs e)
            {
                if (Program.WebView2Environment == null)
                    Program.WebView2Environment = Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(@"C:\Users\Dragon\Downloads\Microsoft.WebView2.FixedVersionRuntime.87.0.664.66.x64", $@"C:\Users\Dragon\Desktop\Test{Guid.NewGuid()}").Result;
                await webView21.EnsureCoreWebView2Async(Program.WebView2Environment);
                webView21.Source = new Uri("http://www.google.com");
            }
    
            private void webView21_CoreWebView2InitializationCompleted_1(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
            {
                if (!e.IsSuccess) { MessageBox.Show($"{e.InitializationException}"); }
    
                if (Deferral != null)
                {
                    Args.NewWindow = webView21.CoreWebView2;
                    Deferral.Complete();
                }
    
                webView21.CoreWebView2.NewWindowRequested += CoreWebView2_NewWindowRequested;
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                webView21.ExecuteScriptAsync($@"window.open('http://www.bing.com', '_blank');");
            }
        }
    }
    
    所以这种工作方式有点奇怪:要生成一个新窗口,可以使用
    ExecuteScriptAsync
    通过JavaScript来实现。在这种情况下,我将打开bing.com的一个新窗口。因此,这将调用
    CoreWebView2\u NewWindowRequested
    。要使事件通过,代码工作(否则它将冻结),它必须经历所有过程。因此,无法设置
    CoreWebView2NewWindowRequestedEven的
    NewWindow
    属性