DEV Community

loading...

TIL: How to Fix WebView2 in WPF TabControl

timothymcgrath profile image Timothy McGrath ・2 min read

There is a new web browser control available in WPF called WebView2. It uses the new Chromium-based Edge browser instead of the IE7 or whatever the original browser control in WPF was using. This allows for modern web pages to be displayed in your WPF app.

Inside my app, I host a WebView2 inside a TabControl, so that for one tab it actually shows an HTML page that looks like part of the WPF app.

However, putting the WebView2 control into the TabControl causes it to not render until the tab is clicked. So, for some users it leaves them with a white screen for a few seconds before the content pops in.

I wanted to eliminate this lag because users are expecting the content to just be there when they click on the tab.

The UI is simple, with a TabControl holdings two tabs, the second one has the WebView2 in it:

<Grid>
    <TabControl
        x:Name="tabs">

        <TabItem Header="Welcome">
            <Grid>
                <TextBlock>Hello!</TextBlock>
            </Grid>
        </TabItem>

        <TabItem Header="Content">
            <Grid>
                <wpf:WebView2
                    x:Name="browser"
                    />
            </Grid>
        </TabItem>
    </TabControl>
</Grid>
Enter fullscreen mode Exit fullscreen mode

The code-behind sets the source of the WebView2:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        browser.Source = new System.Uri("https://www.cnn.com/");

        this.Loaded += (_, __) =>
        {
            Debug.WriteLine("Main Window Loaded");
        };

        browser.CoreWebView2InitializationCompleted += (_, __) =>
        {
            Debug.WriteLine("Web View Initialized");
        };
    }
}
Enter fullscreen mode Exit fullscreen mode

Running this code shows that the WebViewInitializationCompleted event never triggers until the user clicks on the second tab, which triggers the browser to start the navigation.

However, if I put tell WPF to activate that tab, update layout to cause the browser to kick off, and then go back to the original tab, it triggers the initialization completed event immediately and renders the web page immediately:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        browser.Source = new System.Uri("https://www.cnn.com/");

        this.Loaded += (_, __) =>
        {
            Debug.WriteLine("Main Window Loaded");

            tabs.SelectedIndex = 1;
            tabs.UpdateLayout();
            tabs.SelectedIndex = 0;
        };

        browser.CoreWebView2InitializationCompleted += (_, __) =>
        {
            Debug.WriteLine("Web View Initialized");
        };
    }
}
Enter fullscreen mode Exit fullscreen mode

I don't love this fix, but it is the only way I could get the browser to prerender the content ahead of time. I was worried it would show some shakiness as the tabs switched, but that switch is not visible on-screen.

If you're hosting a WebView2 inside a WPF TabControl, this can help to prerender the content before the user clicks on the tab.

Check out the full code here: https://github.com/timothymcgrath/tabwebviewfix

Discussion (0)

pic
Editor guide