1

I am using WebView2 in WPF and I am trying to simulate creating Tabs.

As a first step I am currently trying to simply create a new Tab. My idea for this is to add multiple WebView2 as children of a Grid. If I then later want to show another tab, I would have to reorder the children inside the Grid.

I have looked at Create tabs using WebView2 - Edge but wasn't able to translate this to WPF.

This is my current approach:

MainWindow.xaml

<Window x:Class="WebView2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <DockPanel LastChildFill="True">
        <Button Click="Button_Click" 
                DockPanel.Dock="Top"
                Content="+"></Button>

        <Grid x:Name="TabArea"
              DockPanel.Dock="Bottom">
            
        </Grid>

    </DockPanel>
</Window>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    private Microsoft.Web.WebView2.Wpf.WebView2 initialTab;

    public MainWindow()
    {
        InitializeComponent();

        initialTab = new Microsoft.Web.WebView2.Wpf.WebView2();
        initialTab.Source = new System.Uri("https://www.google.com");
        initialTab.CoreWebView2InitializationCompleted += webView_CoreWebView2InitializationCompleted;
        TabArea.Children.Add(initialTab);
    }

    private async void CoreWebView2_NewWindowRequested(object? sender, Microsoft.Web.WebView2.Core.CoreWebView2NewWindowRequestedEventArgs e)
    {
        e.Handled = true;

        Microsoft.Web.WebView2.Wpf.WebView2 newTab = new Microsoft.Web.WebView2.Wpf.WebView2();
        TabArea.Children.Add(newTab);

        await newTab.EnsureCoreWebView2Async();

        e.NewWindow = newTab.CoreWebView2;
    }

    private void webView_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
    {
        if (!e.IsSuccess) { 
            MessageBox.Show($"{e.InitializationException}"); 
        }

        initialTab.CoreWebView2.NewWindowRequested += CoreWebView2_NewWindowRequested;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {  
        initialTab.ExecuteScriptAsync($@"window.open('http://www.bing.com', '_blank');");
    }

}

Currently when I click the "+"-button instead of creating and showing a new tab, the TabArea either turns completly white or black.

What am I missing to make this work as intended?

frankenapps
  • 5,800
  • 6
  • 28
  • 69
  • You should set `e.Handled = true;` just to completely suppress the popup, otherwise `e.NewWindow = newTab.CoreWebView2;` to show it in the other instance. Look at the descriptions [here](https://stackoverflow.com/a/66191411/3110834). – Reza Aghaei Jul 21 '22 at 10:40
  • Unfortunately it does not work without `e.Handled = true;` either. Instead there is a sort of empty temporary popup window shown before the `TabArea` turns black. – frankenapps Jul 21 '22 at 11:00
  • 1
    As far as I know, WebView2 doesn't really use the concept of tabs - instead it is mostly a 1:1 relationship between WebView2 and a page. If you need to implement similar feature, you'll have to build the tab UI yourself, and use the new environment to create a WebView2, and hide the corresponding WebView2 controls based on the tab buttons, etc. Besides, this sample shows how to [use tabs in webview2](https://github.com/MicrosoftEdge/WebView2Browser) but it uses c++. – Xudong Peng Jul 22 '22 at 10:03
  • @XudongPeng That’s exactly what I am trying to do but in WPF (or .Net, but not WinForms) – frankenapps Jul 22 '22 at 15:36

3 Answers3

3

The following shows how one can use a tab control that hosts WebView2 instances in WPF (each tab contains it's own instance of WebView2). The current behavior, as per the code in the OP, is that a new tab will be created when the NewWindowRequested event is raised. In the code below, this happens when the button is clicked.

I've included step-by-step instructions so that it may be useful for others as well (including beginners).


Pre-requisites:

VS 2022:

  • Open Visual Studio 2022

  • Click enter image description here

  • In VS menu, click File

  • Select New

  • Select Project

  • enter image description here

  • Select WPF Application

    enter image description here

  • Click Next

  • Enter desired project name (ex: WebView2TabTestWpfGC)

  • Click Next

  • For Framework, select .NET 6.0 (Long-term support)

  • Click Create

Open Solution Explorer

  • In VS menu, click View
  • Select Solution Explorer

Set NuGet Default Package Management Format to PackageReference (Optional)

  • In VS menu, click Tools
  • Select Options...
  • Expand NuGet Package Manager by double-clicking it.
  • Click General
  • Under "Package Management", for Default package management format, select PackageReference
  • Click OK

Add NuGet package (Microsoft.Web.WebView2)

  • In Solution Explorer, right click /
  • Select Manage NuGet packages...
  • Click Browse tab
  • In search box, type Microsoft.Web.WebView2
  • Select Microsoft.Web.WebView2, and click Install
  • If a prompt appears, click OK

MainWindow.xaml:

<Window x:Class="WebView2TabTestWpfGC.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WebView2TabTestWpfGC"
        xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
        mc:Ignorable="d"
        Closing="Window_Closing"
        Loaded="Window_Loaded"
        Title="MainWindow" Height="450" Width="800">

    <DockPanel LastChildFill="True">
        <Button Click="Button_Click" 
                DockPanel.Dock="Top"
                Content="+"></Button>

        <Grid x:Name="TabArea"
              DockPanel.Dock="Bottom">

            <TabControl x:Name="tabControl1" ItemsSource="{Binding Path= WebView2Tabs, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" SelectedIndex="{Binding Path= SelectedIndex, Mode=OneWayToSource, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" IsSynchronizedWithCurrentItem="True" />
        </Grid>
    </DockPanel>
</Window>

MainWindow.xaml.cs

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.Wpf;
using System.Diagnostics;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Collections.ObjectModel;
using System.Collections.Generic;

namespace WebView2TabTestWpfGC
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;

        private int _tabCount = 0;
        private int _selectedIndex = 0;

        private ObservableCollection<TabItem> _webView2Tabs = new ObservableCollection<TabItem>();
        public int SelectedIndex
        {
            get { return _selectedIndex; }
            set
            {
                if (_selectedIndex == value)
                    return;

                //set value
                _selectedIndex = value;

                OnPropertyChanged(nameof(SelectedIndex));
            }
        }

        public ObservableCollection<TabItem> WebView2Tabs
        {
            get { return _webView2Tabs; }
            set
            {
                if (_webView2Tabs == value)
                    return;

                //set value
                _webView2Tabs = value;

                OnPropertyChanged(nameof(WebView2Tabs));
            }
        }
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            AddTab("https://www.microsoft.com");
        }

   
        private void AddTab(string url, string? headerText = null, string? userDataFolder = null)
        {
            AddTab(new Uri(url), headerText, userDataFolder);
        }
        private void AddTab(Uri uri, string? headerText = null, string? userDataFolder = null)
        {
            //increment
            _tabCount++;

            if (headerText == null)
                headerText = $"Tab {_tabCount}";
            
            //if userDataFolder hasn't been specified, create a folder in the user's temp folder
            //each WebView2 instance will have it's own folder
            if (String.IsNullOrEmpty(userDataFolder))
                userDataFolder = System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetExecutingAssembly().Location) + _tabCount);

            //create new instance setting userDataFolder
            WebView2 wv = new WebView2() { CreationProperties = new CoreWebView2CreationProperties() { UserDataFolder = userDataFolder } };
            wv.CoreWebView2InitializationCompleted += WebView2_CoreWebView2InitializationCompleted;

            //create TextBlock
            TextBlock textBlock = new TextBlock();

            //add new Run to TextBlock
            textBlock.Inlines.Add(new Run(headerText));

            //add new Run to TextBlock
            textBlock.Inlines.Add(new Run("   "));

            //create Run
            Run runHyperlink = new Run("X");
            runHyperlink.FontFamily = new FontFamily("Monotype Corsiva");
            runHyperlink.FontWeight = FontWeights.Bold;
            runHyperlink.Foreground = new SolidColorBrush(Colors.Red);

            //add Run to HyperLink
            Hyperlink hyperlink = new Hyperlink(runHyperlink) { Name = $"hyperlink_{_tabCount}"};
            hyperlink.Click += Hyperlink_Click;

            //add Hyperlink to TextBlock
            textBlock.Inlines.Add(hyperlink);

            //create new instance and set Content
            HeaderedContentControl hcc = new HeaderedContentControl() { Content = textBlock };

            //add TabItem
            _webView2Tabs.Add(new TabItem { Header = hcc, Content = wv, Name = $"tab_{_tabCount}" });

            //navigate
            wv.Source = uri;

            //set selected index
            tabControl1.SelectedIndex = _webView2Tabs.Count - 1;
        }

        private void LogMsg(string msg, bool includeTimestamp = true)
        {
            if (includeTimestamp)
                msg = $"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.fff")} - {msg}";

            Debug.WriteLine(msg);
        }

        protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private void RemoveTab(int index)
        {
            if (index >= 0 && index < _webView2Tabs.Count)
            {
                WebView2 wv = (WebView2)_webView2Tabs[index].Content;

                //get userDataFolder location
                //string userDataFolder = wv.CreationProperties.UserDataFolder;
                string userDataFolder = wv.CoreWebView2.Environment.UserDataFolder;

                //unsubscribe from event(s)
                wv.CoreWebView2InitializationCompleted -= WebView2_CoreWebView2InitializationCompleted;
                wv.CoreWebView2.NewWindowRequested -= CoreWebView2_NewWindowRequested;

                //get process
                var wvProcess = Process.GetProcessById((int)wv.CoreWebView2.BrowserProcessId);
             
                //dispose
                wv.Dispose();

                //wait for WebView2 process to exit
                wvProcess.WaitForExit();

                //for security purposes, delete userDataFolder
                if (!String.IsNullOrEmpty(userDataFolder) && System.IO.Directory.Exists(userDataFolder))
                {
                    System.IO.Directory.Delete(userDataFolder, true);
                    LogMsg($"UserDataFolder '{userDataFolder}' deleted.");
                }
                    
                //TabItem item = _webView2Tabs[index];
                LogMsg($"Removing {_webView2Tabs[index].Name}");

                //remove
                _webView2Tabs.RemoveAt(index);
            }
            else
            {
                LogMsg($"Invalid index: {index}; _webView2Tabs.Count: {_webView2Tabs.Count}");
            }
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            if (_webView2Tabs.Count > 0)
            {
                //get instance of WebView2 from last tab
                WebView2 wv = (WebView2)_webView2Tabs[_webView2Tabs.Count - 1].Content;

                //if CoreWebView2 hasn't finished initializing, it will be null
                if (wv.CoreWebView2?.BrowserProcessId > 0)
                {
                    await wv.ExecuteScriptAsync($@"window.open('https://www.google.com/', '_blank');");
                }    
            }
            else
            {
                AddTab("https://www.microsoft.com");
            }
        }

        private void CoreWebView2_NewWindowRequested(object? sender, Microsoft.Web.WebView2.Core.CoreWebView2NewWindowRequestedEventArgs e)
        {
            e.Handled = true;

            AddTab(e.Uri);
        }

        private void Hyperlink_Click(object sender, RoutedEventArgs e)
        {
            Hyperlink hyperlink = (Hyperlink)sender;

            LogMsg($"Hyperlink_Click - name: {hyperlink.Name}");

            string hyperLinkNumStr = hyperlink.Name.Substring(hyperlink.Name.IndexOf("_") + 1);
            int hyperLinkNum = 0;

            //try to convert to int
            Int32.TryParse(hyperLinkNumStr, out hyperLinkNum);

            int index = 0;

            //it's possible that an 'X' was clicked on a tab that wasn't selected
            //since both the tab name and hyperlink name end with the same number,
            //get the number from the hyperlink name and use that to find the matching 
            //tab name
            for (int i = 0; i < _webView2Tabs.Count; i++)
            {
                TabItem item = _webView2Tabs[i];
                
                if (item.Name == $"tab_{hyperLinkNum}")
                {
                    index = i;
                    break;
                }
            }

            //set selected index
            tabControl1.SelectedIndex = index;

            RemoveTab(index);
        }
        private void WebView2_CoreWebView2InitializationCompleted(object? sender, CoreWebView2InitializationCompletedEventArgs e)
        {
            LogMsg("WebView2_CoreWebView2InitializationCompleted");
            if (!e.IsSuccess)
                LogMsg($"{e.InitializationException}");

            if (sender != null)
            {
                WebView2 wv = (WebView2)sender;
                wv.CoreWebView2.NewWindowRequested += CoreWebView2_NewWindowRequested;
            }
        }

        private void Window_Closing(object sender, CancelEventArgs e)
        {
            if (_webView2Tabs != null && _webView2Tabs.Count > 0)
            {
                for (int i = 0; i < _webView2Tabs.Count - 1; i++)
                {
                    //remove all tabs which will dispose of each WebView2
                    RemoveTab(i);
                }
            }
        }
    }
}

Note: In the code above, a userDataFolder is created for each tab (each instance of WebView2) and should be deleted when the 'X' for the tab is clicked. The idea to use a Hyperlink to close the tab is something I found somewhere online, but unfortunately I don't recall where I found it.

Known issue: When the window is closed by clicking the 'X' (for the Window), the user data folders aren't deleted.

Disclaimer: The code above should be considered proof-of-concept and has had limited testing.


Here's a demo:

enter image description here


Resources:

Tu deschizi eu inchid
  • 4,117
  • 3
  • 13
  • 24
  • While not technically the answer as to why my original approach did not work as expected, this helped me a lot with figuring out how to at least create some sort of tab using `WebView2`, so I am going to accept this. – frankenapps Jul 23 '22 at 10:21
  • @frankenapps: I've added another answer which describes the issues with the original code, and how to fix it. – Tu deschizi eu inchid Jul 23 '22 at 16:43
2

I'm not exactly sure what you're trying to accomplish, because you mentioned "Tabs", but don't show any code that uses a TabControl.

There are three main issues in the original code.

  1. Button_Click event handler (and associated code) is missing.

  2. In CoreWebView2_NewWindowRequested the following statement is causing WebView2 to crash: e.NewWindow = newTab.CoreWebView2;. It should be: newTab.Source = new Uri(e.Uri);.

  3. When adding newTab using TabArea.Children.Add(newTab);, the WebView2 instance is being hidden behind initialTab instance so it's not visible.

MainWindow.xaml:

<DockPanel LastChildFill="True">
    <Button Click="Button_Click" 
            DockPanel.Dock="Top"
            Content="+"></Button>

    <Grid x:Name="TabArea"
          DockPanel.Dock="Bottom">

    </Grid>

</DockPanel>

Option 1:

The following is more similar to the code in your OP, but it may need to be modified to achieve the desired behavior (see the comments within the code for other potential issues):

MainWindow.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Web.WebView2;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.Wpf;
using System.Diagnostics;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Collections.ObjectModel;

namespace WebView2TabTestWpfGC
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Microsoft.Web.WebView2.Wpf.WebView2 initialTab;

        private int _tabCount = 0; //added

        public MainWindow()
        {
            InitializeComponent();

            //create new instance
            initialTab = new Microsoft.Web.WebView2.Wpf.WebView2();

            //subscribe to WebView2 event(s)
            initialTab.CoreWebView2InitializationCompleted += webView_CoreWebView2InitializationCompleted;

            LogMsg("MainWindow constructor - before setting source");

            //setting the Source property causes implicit initialization,
            //if CoreWebView2 hasn't been already initialized explicitly
            //by using 'EnsureCoreWebView2Async'. it also navigates to
            //the specified URL
            initialTab.Source = new System.Uri("https://www.google.com");

            LogMsg("MainWindow constructor - after setting source");

            //CoreWebView2InitializationCompleted should be subscribed to, before setting the Source
            //property, because setting the Source property causes implicit initialization
            //initialTab.CoreWebView2InitializationCompleted += webView_CoreWebView2InitializationCompleted;

            //add to Grid
            TabArea.Children.Add(initialTab);
        }

        private void LogMsg(string msg, bool includeTimestamp = true)
        {
            if (includeTimestamp)
                msg = $"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.fff")} - {msg}";

            Debug.WriteLine(msg);
        }

        private async void CoreWebView2_NewWindowRequested(object? sender, Microsoft.Web.WebView2.Core.CoreWebView2NewWindowRequestedEventArgs e)
        {
            e.Handled = true;

            //create new instance
            Microsoft.Web.WebView2.Wpf.WebView2 newTab = new Microsoft.Web.WebView2.Wpf.WebView2();

            //For testing, the previous WebView2 instance is hidden
            //so that the new instance will be visible.
            //hide previous WebView2 instance
            //
            //ToDo: change to desired behavior
            LogMsg($"TabArea.Children.Count: {TabArea.Children.Count}");
            TabArea.Children[TabArea.Children.Count - 1].Visibility = Visibility.Hidden;

            //add to Grid
            TabArea.Children.Add(newTab);

            LogMsg("CoreWebView2_NewWindowRequested - before EnsureCoreWebView2Async");

            //it's recommended to create the userData folder in %ProgramData%\YourApplicationName
            //each instance of WebView2 should have it's own userDataFolder, otherwise 
            //additional code needs to be added to prevent deadlocks/crashes.
            //if a userDataFolder isn't specified, it will be created in the same location
            //as this program's executable.

            await newTab.EnsureCoreWebView2Async();

            //for testing the userDataFolder is created in the user's temp folder
            //string userDataFolder = System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetExecutingAssembly().Location) + _tabCount);
            //CoreWebView2Environment coreWebView2Environment = await CoreWebView2Environment.CreateAsync(null, userDataFolder, null);

            //await CoreWebView2 initialization
            //await newTab.EnsureCoreWebView2Async(coreWebView2Environment);

            LogMsg("CoreWebView2_NewWindowRequested - after EnsureCoreWebView2Async");

            //e.NewWindow = newTab.CoreWebView2;

            //set Source property (navigate to the specified URL)
            newTab.Source = new Uri(e.Uri);

            LogMsg("CoreWebView2_NewWindowRequested - after setting source");
        }

        private void webView_CoreWebView2InitializationCompleted(object? sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
        {
            LogMsg("webView_CoreWebView2InitializationCompleted");

            if (!e.IsSuccess)
            {
                MessageBox.Show($"{e.InitializationException}");
            }

            //subscribe to CoreWebView2 event(s)
            initialTab.CoreWebView2.NewWindowRequested += CoreWebView2_NewWindowRequested;
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            LogMsg("Button_Click");

            //if CoreWebView2 hasn't finished initializing, it will be null
            if (initialTab.CoreWebView2?.BrowserProcessId > 0)
            {
                //execute specified JavaScript
                await initialTab.ExecuteScriptAsync($@"window.open('https://www.microsoft.com/', '_blank');");
            }
        }
    }
}

Option 2:

The following is a WPF version of Create tabs using WebView2 - Edge which results in a new window being displayed.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Web.WebView2;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.Wpf;
using System.Diagnostics;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Collections.ObjectModel;

namespace WebView2TabTestWpfGC
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Microsoft.Web.WebView2.Wpf.WebView2 initialTab;

        private int _tabCount = 0; //added

        public Microsoft.Web.WebView2.Core.CoreWebView2Deferral Deferral { get; set; }
        public Microsoft.Web.WebView2.Core.CoreWebView2NewWindowRequestedEventArgs Args { get; set; }

        public MainWindow()
        {
            InitializeComponent();

            //create new instance
            initialTab = new Microsoft.Web.WebView2.Wpf.WebView2();

            //subscribe to WebView2 event(s)
            initialTab.CoreWebView2InitializationCompleted += webView_CoreWebView2InitializationCompleted;

            LogMsg("MainWindow constructor - before setting source");

            //setting the Source property causes implicit initialization,
            //if CoreWebView2 hasn't been already initialized explicitly
            //by using 'EnsureCoreWebView2Async'. it also navigates
            //to the specified URL
            initialTab.Source = new System.Uri("https://www.google.com");

            LogMsg("MainWindow constructor - after setting source");

            //CoreWebView2InitializationCompleted should be subscribed to, before setting the Source
            //property, because setting the Source property causes implicit initialization
            //initialTab.CoreWebView2InitializationCompleted += webView_CoreWebView2InitializationCompleted;
             
            //add to Grid
            TabArea.Children.Add(initialTab);
        }

        private void LogMsg(string msg, bool includeTimestamp = true)
        {
            if (includeTimestamp)
                msg = $"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.fff")} - {msg}";

            Debug.WriteLine(msg);
        }

        private void CoreWebView2_NewWindowRequested(object? sender, Microsoft.Web.WebView2.Core.CoreWebView2NewWindowRequestedEventArgs e)
        {
            //create new instance
            MainWindow mainWindow = new MainWindow();

            mainWindow.Args = e;
            mainWindow.Deferral = e.GetDeferral();
            mainWindow.Show();
        }

        private void webView_CoreWebView2InitializationCompleted(object? sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
        {
            LogMsg("webView_CoreWebView2InitializationCompleted");

            if (!e.IsSuccess) { MessageBox.Show($"{e.InitializationException}"); }

            if (Deferral != null)
            {
                Args.NewWindow = initialTab.CoreWebView2;
                Deferral.Complete();
            }

            initialTab.CoreWebView2.NewWindowRequested += CoreWebView2_NewWindowRequested;
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            LogMsg("Button_Click");

            //if CoreWebView2 hasn't finished initializing, it will be null
            if (initialTab.CoreWebView2?.BrowserProcessId > 0)
            {
                //execute specified JavaScript
                await initialTab.ExecuteScriptAsync($@"window.open('https://www.microsoft.com/', '_blank');"); //this raises NewWindowRequested
                //await initialTab.ExecuteScriptAsync($@"window.open('https://www.microsoft.com/', '_self');"); //this doesn't raise NewWindowRequested
            }
        }
    }
}

Resources:

Tu deschizi eu inchid
  • 4,117
  • 3
  • 13
  • 24
  • Awesome. Option 1 was what I was looking for. You are right, I forgot to include the Click handler in the question. Issue 3 I wasn't aware of, but I think reordering the children should also fix this. Issue 2 was the main culprint in my case thanks for clearing that up. – frankenapps Jul 24 '22 at 08:51
  • The reason why I did not include the WPF `TabControl` is that I would like to build my own GUI (in HTML/CSS/JS) in another WebView2 Control for the TabBar similar to the [WebView2Browser](https://github.com/MicrosoftEdge/WebView2Browser). – frankenapps Jul 24 '22 at 08:52
0

if you replace the grid "TabArea" by a real tab control, then you can handle the tab.add(new webView) in the NewWindowRequested so you will have sereval real tabs?? Bye

GCamel
  • 612
  • 4
  • 8