For the sake of completeness, I was able to achieve the same thing thanks to David Risney's explanation. Unfortunately it didn't include any code, but I achieved this using 1.0.721-prerelease
and 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());
}
}
}
Form1.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');");
}
}
}
So the way this works is kinda weird: To spawn a new window, you can do it through JavaScript using ExecuteScriptAsync
. In this case I'm opening a new window to bing.com. So, that makes a call to CoreWebView2_NewWindowRequested
. For the event to pass and the code to work (otherwise it will freeze) it must go through it all. So, you cannot set the NewWindow
property of the CoreWebView2NewWindowRequestedEventArgs
inside the event that's currently happening.
The solution is to take the event data (args & deferral) to the new form, show it, and upon load and after the CoreWebView2
property of the control is not null / has initialized, by calling CoreWebView2InitializationCompleted
, check if args/deferral are not null and then call the defer as Complete()
(this is basically like a JS promise) AND here you can set the NewWindow
property as CoreWebView2
has been initialized and therefore it's not null.
Hopefully this will answer your question and future readers. With this code, I was able to make it work.