2

I want to navigate to the URL rather than it opening a separate instance.
No matter what I do it still opens another instance of WebView2.

private void CoreWebView2_NewWindowRequested(object sender,
            CoreWebView2NewWindowRequestedEventArgs e)
        {
            //e.NewWindow = webView21.CoreWebView2;
            e.NewWindow = (CoreWebView2)sender;
            //e.Handled = true;
        }

here's the original post, what do I need to do for it to handle the new window request?

Jimi
  • 29,621
  • 8
  • 43
  • 61

2 Answers2

5

To receive a notification when a new Popup Windows is requested, subscribe to the the NewWindowRequested of CoreWebView2.

The event is raised when there's a request to generate a Popup. Clicking a link that just cause the Browser to navigate to a different URI doesn't raise the event (no popup).
A new Popup Window can be requested if the User clicks the Open link in new window (sic) option of the standard ContextMenu provided by the Browser.
Or if the Web Page generates one without user intervention.

Unfortunately, the e.IsUserInitiated property is always true, so you may have a hard time determining (without injecting JavaScripts) whether the popup should be blocked (in case you want to, that is).

When a new Window is requested, you can block it indiscriminately setting e.Handled = true

If you want to open the new Window URI to the same Window, you can specify either:

e.Handled = true;
e.NewWindow = (CoreWebView2)sender;
// or  
e.Handled = true;
((CoreWebView2)sender).Navigate(e.Uri);

Sample WebView2 main handler Form:

using Microsoft.Web.WebView2.Core;

public partial class MainForm : Form
{
    public MainForm() => InitializeComponent();

    protected override async void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        webView2.CoreWebView2InitializationCompleted += OnCoreWebView2InitializationCompleted;
        var env = await CoreWebView2Environment.CreateAsync(null, null, null);
        await webView2.EnsureCoreWebView2Async(env);
        webView2.Source = new Uri("https://www.somesite.com");
    }

    private void OnCoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
    {
        webView2.CoreWebView2.NewWindowRequested += OnNewWindowRequested;
    }

    private void OnNewWindowRequested(object sender, CoreWebView2NewWindowRequestedEventArgs e)
    {
        // Open the Uri requested in the current Window
        e.Handled = true;
        ((CoreWebView2)sender).Navigate(e.Uri);
    }
  
    // Or, if you want to handle Popup Windows using your own Form template
    // => Note that it's the same event handler as above, pick one, not both!
    private void OnNewWindowRequested(object sender, CoreWebView2NewWindowRequestedEventArgs e)
    {
        // Open the Uri requested in a new instance of the PopupWindow Form
        var deferral = e.GetDeferral();
        e.Handled = true;
        var popup = new PopupWindow(deferral, e);
        popup.Show();
    }
}

If you instead want to create a new Form that will show the popup, you need a Form template (it can be just a Form that contains a WebView2 Control) that receive the CoreWebView2Deferral returned by e.GetDeferral().

In the initialization procedure of this Form check whether the CoreWebView2Deferral object is null. If it's not, complete the deferred event by calling its Complete() method.

Then subscribe to the NewWindowRequested event to perform the same action when a new Popup Window is requested (unless you want to block it).

Of course you can show these Forms inside a Tabbed Control, to generate a standard tabbed view, common in all WebBrowsers.

Sample PopupWindow Form:

using Microsoft.Web.WebView2.Core;
using System.Windows.Forms;

public partial class PopupWindow : Form
{
    public PopupWindow() => InitializeComponent();
    public PopupWindow(CoreWebView2Deferral deferral, CoreWebView2NewWindowRequestedEventArgs args) 
        : this() {
        Core2Deferral = deferral;
        NewWindowArgs = args;
    }

    protected virtual CoreWebView2Deferral Core2Deferral { get; private set; }
    protected virtual CoreWebView2NewWindowRequestedEventArgs NewWindowArgs { get; private set; }

    protected async override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        webView2.CoreWebView2InitializationCompleted += OnCoreWebView2InitializationCompleted;

        var env = await CoreWebView2Environment.CreateAsync(null, null, null);
        await webView2.EnsureCoreWebView2Async(env);
    }

    private void OnCoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
    {
        webView2.CoreWebView2.Settings.AreDefaultContextMenusEnabled = true;
        if (Core2Deferral != null) {
            NewWindowArgs.NewWindow = webView2.CoreWebView2;
            Core2Deferral.Complete();
        }
        webView2.CoreWebView2.NewWindowRequested += OnNewWindowRequested;
    }

    private void OnNewWindowRequested(object sender, CoreWebView2NewWindowRequestedEventArgs e)
    {
        e.Handled = true;
        var popup = new PopupWindow(e.GetDeferral(), e);
        popup.Show();
    }
}
Jimi
  • 29,621
  • 8
  • 43
  • 61
0

How about making it works like real web browsers. Simply, opens in an new Tab. Just with a few lines of codes ;)

At first, create a new class which inherits from WebView2 and include a TabControl field inside it:

internal class WebViewInTab:WebView2
{
    TabControl tabCtrl;

    public WebViewInTab(TabControl tabCtrl) :base()
        {
            Dock = DockStyle.Fill; // necessary for showing 
            this.tabCtrl = tabCtrl; // for adding new TabPage controls
            CoreWebView2InitializationCompleted += WebViewInTab_CoreWebView2InitializationCompleted;
        }

Then, you'll use this custom webview2 to create new webview2 objects every time CoreWebView2.NewWindowRequested event is raised. So to handle the event:

private void WebViewInTab_CoreWebView2InitializationCompleted(object? sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
{
    CoreWebView2.NewWindowRequested += CoreWebView2_NewWindowRequested; // This is the man
    CoreWebView2.DocumentTitleChanged += CoreWebView2_DocumentTitleChanged; // Just cosmetic code
}

After that, you'll handle the new window by yourself, i.e. , Just add a new TabPage control with our custom webview2 to the TabControl TabPages collection. Of course, not forgeting the Uri from handler arg.

private void CoreWebView2_NewWindowRequested(object? sender, Microsoft.Web.WebView2.Core.CoreWebView2NewWindowRequestedEventArgs e)
    {
        e.Handled = true; // let the default new window 

        TabPage tpage = new TabPage(); // boy

        tpage.Controls.Add(new WebViewInTab(tabCtrl) { Source = new Uri(e.Uri)}); // toy

        tabCtrl.TabPages.Add(tpage); // daddy
        tabCtrl.SelectedTab = tpage; // user expectation
    }

//Just cosmetic code
private void CoreWebView2_DocumentTitleChanged(object? sender, object e)
    {
        int last = tabCtrl.TabPages.Count - 1;
        tabCtrl.TabPages[last].Text = CoreWebView2.DocumentTitle
    }
}

Finally, :) start the recursion-ready operation in the main app form constructor.

public Form1()
        {
            InitializeComponent();
            string uriAdd = "https://www.w3schools.com/";
            tabControl1.TabPages[0].Controls.Add(new WebViewInTab(tabControl1) { Source = new Uri(uriAdd) });
        }
90Degree
  • 199
  • 1
  • 5