Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Why won't the WebView2 navigate when the Window is not in focus? #1845

Closed
michaldivis opened this issue Oct 19, 2021 · 8 comments
Closed

Why won't the WebView2 navigate when the Window is not in focus? #1845

michaldivis opened this issue Oct 19, 2021 · 8 comments
Assignees

Comments

@michaldivis
Copy link

michaldivis commented Oct 19, 2021

Hi,

I have a question / maybe a bug report. This is what's happening to me:

I have a WebView2 on a Window, let's call it mainWindow. I open another Window, a dialogWindow. The dialogWindow invokes a callback to the mainWindow to update the HTML file loaded into the WebView2. However, even after setting the WebView2's Source property, no navigation will happen until the dialogWindow is closed. Only then is the NavigationStarting event triggered.

Is that supposed to be the case? An if so, is there a way I can get the WebView2 to update while the dialogWindow is open? Thanks for any advice!

Here's more information about my app:

It's a .NET 5.0 WPF app and I'm using Microsoft.Web.WebView2 version 1.0.902.49.

My mainWindow, that holds the WebView2 control opens the dialogWindow like this, passing in a callback function to refresh the HTML displayed in the WebView2:

// I'm using MVVM in the actual app, but omitting that here, so the code isn't needlessly complex.
public class MainWindow : Window{
    private void OpenDialogWindow() {
        Action<string> callback = newHtmlFilePath => webView2.Source = new Uri(newHtmlFilePath);
        var dialogWindow = new DialogWindow(callback);
        dialogWindow.ShowDialog();
    }
}
@champnic
Copy link
Member

Hey @michaldivis - I don't believe WebView2 should have a limitation here. If you put a breakpoint on setting the Source, can you confirm that the Source property is actually being set before the DialogWindow is closed? Which DialogWindow class is that, and when is the callback expected to be fired?

@champnic champnic self-assigned this Oct 22, 2021
@michaldivis
Copy link
Author

michaldivis commented Oct 25, 2021

Hey @champnic , I can confirm that the Source property is being set before the dialog window is closed, however, the NavigationStarting is triggered after the dialog window is closed.

And to answer your second question, both the MainWindow and DialogWindow inherit from the default WPF Window class. I'll tweak the example above to reflect that.

@michaldivis
Copy link
Author

I've been messing with (but haven't changed any code) the app some more and now the app occasionally crashes after loading an item from the dialog window. This is the error I get in the Event Viewer:

Faulting application name: MyApp.exe, version: 1.0.0.0, time stamp: 0x60c8ffcd
Faulting module name: EmbeddedBrowserWebView.dll, version: 95.0.1020.30, time stamp: 0x616f669f
Exception code: 0x80000003
Fault offset: 0x00000000002beb0d
Faulting process id: 0x51c0
Faulting application start time: 0x01d7c969452ab314
Faulting application path: C:\Projects\MyApp\src\MyApp\bin\x64\Debug\net5.0-windows\win-x64\MyApp.exe
Faulting module path: C:\Program Files (x86)\Microsoft\EdgeWebView\Application\95.0.1020.30\EBWebView\x64\EmbeddedBrowserWebView.dll
Report Id: fb097d63-3753-45e8-8f52-ccdc6fe741b3
Faulting package full name: 
Faulting package-relative application ID: 

Note that I've replaced the name of the actual app.

@michaldivis
Copy link
Author

Update: I've resolved the issue (kind of).
I've been able to fix the bug in my production app, however, when I wasn't able to replicate the behaviour in my reproduction repo.

My reproduction repo: https://github.com/michaldivis/WebView2DialogNavigation (warning: I couldn't reproduce the bug, but this repo might at least give you an idea of what my production app is like).

The reproduction repo is very similar to what the actual app does, but for some reason, the bug just doesn't occur in the reproduction repo.

After further testing, I might have figured out what the problem was. Here are two very similar methods to do the same thing, one works, the other doesn't:

Method #1 - works

Using this method, when item selected, the WebView2's Source property gets changed, the NavigationStarting event fires and the html content updates correctly.

public ICommand OpenAddItemsCommand => new DarkAsyncCommand(OpenAddItemsInvokedByWpfControl); //this gets trigged by a Button control

private async Task OpenAddItemsInvokedByWpfControl()
{
    await _navigationService.PushDialogAsync(AddItemAndUpdateContent); //passing in the AddItemAndUpdateContent method as a callback
}

private void AddItemAndUpdateContent(Item newItem)
{
    HtmlContent = AddItemToHtml(HtmlContent, newItem);
}

The OpenAddItemsCommand gets triggered by a Button click (the command is bound to the Buttons's Command property).

Method #2 - does NOT work

Using this method, when item selected, the WebView2's Source property gets changed, however, the NavigationStarting event doesn't fire and the html content does not update until the dialog window is closed.

public ICommand LinkClickedCommand => new DarkAsyncCommand<string>(LinkClicked); //this gets triggered from the WebView2's NavigationStarting event (only if the url matches a specific pattern)

private async Task LinkClicked(string link)
{
    if (string.IsNullOrEmpty(link))
    {
        return;
    }

    var addItemPattern = Regex.Match(link, @"ADD_ITEM");
    if (addItemPattern.Success)
    {
        await _navigationService.PushDialogAsync(AddItemAndUpdateContent); //passing in the AddItemAndUpdateContent method as a callback
    }
}

Here the LinkClickedCommand gets triggered by a WebView2 event, like so:

private void WebView2_NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs e)
{
    string linkName = Path.GetFileName(e.Uri);

    var isTempFileName = _fileManager.IsTempFilePath(linkName);

    if (isTempFileName)
    {
        return;
    }

    e.Cancel = true;

    TriggerLinkClicked(linkName);
}

private void TriggerLinkClicked(string link)
{
    bool canExecute = LinkClickedCommand?.CanExecute(link) ?? false;

    if (canExecute is false)
    {
        return;
    }

    LinkClickedCommand?.Execute(link);
}

My conclusion

I still have no idea why this is happening and as I've metioned, I'm having trouble even replicating the issue so don't take this as a fault of the WebView2 team. I'm simply trying to solve a weird bug here.

My only guess is that invoking the LinkClickedCommand from the WebView2's event might be triggering the command from a different thread which could cause the WebView2 to not update (but I'm really not sure at all about that).

I'll appreciate any help here. Thanks!

@champnic
Copy link
Member

Hey @michaldivis - thanks for the extra digging and details.

The cause might be that in the case where it doesn't work, you are doing it from within a NavigationStarting event handler. This will block the WebView2 from doing further navigations, because it's waiting for the outcome of the first event handler (for example, the WebView2 needs to know whether or not to cancel the navigation).

The easiest workaround is to make TriggerLinkClicked an async function, so that when you call it from webview2_NavigationStarting it doesn't block and the event handler can complete and unblock the WebView2. Want to give something like that a try?

Thanks!

@michaldivis
Copy link
Author

Hey @champnic , that's it! Thanks!

The TriggerLinkClicked was using my NavigationService to open the dialog window (with Window.ShowDialog()) which would block the thread until the dialog was closed, and that caused the webview2_NavigationStarting event to wait for it.

If I open the dialog window normally (using Window.Show(), which doesn't block the thread), the webview2_NavigationStarting can finish and any changes triggered from the dialog window now update immediately in the WebView2.

Thanks for all the help!

@champnic
Copy link
Member

Glad you got it working @michaldivis! :)

@david-randoll
Copy link

Hey @michaldivis - thanks for the extra digging and details.

The cause might be that in the case where it doesn't work, you are doing it from within a NavigationStarting event handler. This will block the WebView2 from doing further navigations, because it's waiting for the outcome of the first event handler (for example, the WebView2 needs to know whether or not to cancel the navigation).

The easiest workaround is to make TriggerLinkClicked an async function, so that when you call it from webview2_NavigationStarting it doesn't block and the event handler can complete and unblock the WebView2. Want to give something like that a try?

Thanks!

Hey, thanks! I have a similar issue with OpenFileDialog where if I navigate away from the BlazorWebView it crashes the dialog. But changing the method to async works!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants