-1

I'm implementing a VSTO add-in with WebView2. I would like to make a button clicking on which launches a non-IE browser hosting a webpage.

Here is UserControl1.cs:

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

namespace My_Addin
{
    public partial class BrowserUserControl : UserControl
    {
        private WebView2 webView;

        public BrowserUserControl()
        {
            InitializeComponent();
            InitializeAsync();
        }

        private void WebView_NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs e)
        {
            Debug.WriteLine("inside WebView_NavigationStarting");
            // Handle navigation starting if necessary
        }

        private async void InitializeAsync()
        {
            try
            {
                var env = await CoreWebView2Environment.CreateAsync(userDataFolder: @"C:\Users\softtimur\VSTO");
                Debug.WriteLine("inside InitializeAsync 1");

                webView = new WebView2
                {
                    Dock = DockStyle.Fill,
                };

                Controls.Add(webView);

                await webView.EnsureCoreWebView2Async(env);
                Debug.WriteLine("inside InitializeAsync 2");

                webView.NavigationStarting += WebView_NavigationStarting;
                Debug.WriteLine("inside InitializeAsync 3");
                webView.CoreWebView2InitializationCompleted += WebView_CoreWebView2InitializationCompleted;
                Debug.WriteLine("inside InitializeAsync 4");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Initialization failed with exception: {ex}");
            }
        }

        private void WebView_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
        {
            Debug.WriteLine("inside WebView_CoreWebView2InitializationCompleted 1");
            if (e.IsSuccess)
            {
                Debug.WriteLine("inside WebView_CoreWebView2InitializationCompleted 2");
                webView.CoreWebView2.Navigate("https://www.google.fr");
            }
            else
            {
                MessageBox.Show($"WebView2 wasn't initialized successfully. Error: {e.InitializationException}");
            }
        }
    }

}

And the button:

private void button2_Click(object sender, RibbonControlEventArgs e)
{    
    using (var form = new Form())
    {
        form.Controls.Add(new BrowserUserControl { Dock = DockStyle.Fill });
        form.ShowDialog();
    }
}

Clicking on the button does launch a window, but it's a blank page. Inspecting the page does not give useful information.

In the output console, it shows inside InitializeAsync but not inside WebView_CoreWebView2InitializationCompleted. Under C:\Users\softtimur\VSTO, there is indeed a folder EBWebView created.

enter image description here

Does anyone know what's the right way to make such a button?

Eugene Astafiev
  • 47,483
  • 3
  • 24
  • 45
SoftTimur
  • 5,630
  • 38
  • 140
  • 292
  • There's no point in subscribing to `webView.CoreWebView2InitializationCompleted` after initialization has already completed. – Tu deschizi eu inchid Jun 20 '23 at 04:31
  • The following may be of interest: https://stackoverflow.com/a/73846538/10024425 and https://stackoverflow.com/a/66551736/10024425 – Tu deschizi eu inchid Jun 20 '23 at 04:34
  • @Tudeschizieuinchid I cannot make the code work on my side. – SoftTimur Jun 21 '23 at 02:35
  • Please update your post by appending the latest code that you're using. There's no need to call `Navigate` inside of `WebView_CoreWebView2InitializationCompleted`. If the initialization was performed properly, then the call to `Navigate` can be placed after the call to the initialization method. – Tu deschizi eu inchid Jun 21 '23 at 03:00

2 Answers2

0

The WebView2 control provides two ways to handle asynchronous initialization of the WebView2's CoreWebView2 instance. The WebView2.EnsureCoreWebView2Async method gives you more control over initialization parameters but is hard to use with a XAML declarative style WebView2 control. If you declare your WebView2 control in XAML then you can use the WebView2.CoreWebView2InitializationCompleted event which will be raised once initialization completes (successfully or with failure - check the event args).

It is possible to use both the EnsureCoreWebView2Async method and the CoreWebView2InitializationCompleted event but you must subscribe to the event before calling the method. Once the method completes, initialization has already happened. If you subscribe to the event after that, the event won't be raised because initialization is complete.

                var env = await CoreWebView2Environment.CreateAsync(userDataFolder: @"C:\Users\softtimur\VSTO");
                Debug.WriteLine("inside InitializeAsync 1");

                webView = new WebView2
                {
                    Dock = DockStyle.Fill,
                };

                Controls.Add(webView);

                // Must subscribe before calling EnsureCoreWebView2Async
                webView.CoreWebView2InitializationCompleted += WebView_CoreWebView2InitializationCompleted; 
                await webView.EnsureCoreWebView2Async(env);
                Debug.WriteLine("inside InitializeAsync 2");

                webView.NavigationStarting += WebView_NavigationStarting;
                Debug.WriteLine("inside InitializeAsync 3");
                // Too late
                // webView.CoreWebView2InitializationCompleted += WebView_CoreWebView2InitializationCompleted; 
                Debug.WriteLine("inside InitializeAsync 4");
David Risney
  • 3,886
  • 15
  • 16
-1

You are trying initialize the webview2 instance in the form's constructor. That is too early I suppose. Try to choose any other event for that, for example, the Load one.

public BrowserUserControl()
{
   InitializeComponent();
   Load += BrowserUserControl_Load;
}

private async void BrowserUserControl_Load(object sender, EventArgs e)
{
   await InitializeAsync();
}
Eugene Astafiev
  • 47,483
  • 3
  • 24
  • 45