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

BlazorWebView for WPF Documenation how access the underlying WebView2 to set additionalBrowserArguments or CreationProperties.BrowserExecutableFolder #3861

Closed
MichaelPeter opened this issue Dec 26, 2021 · 9 comments
Labels
area-blazor Blazor Hybrid / Desktop, BlazorWebView feature-blazor-windesktop Issues in Blazor in WPF or WinForms proposal/open s/duplicate 2️⃣ This issue or pull request already exists

Comments

@MichaelPeter
Copy link

MichaelPeter commented Dec 26, 2021

Description

I want to use the WebGPU feature of a preview build of edge canary with the WPF BlazorWebView.

To do this I need to set the Binaries of the webview2, which can only be done over the underlying Wpf WebView2 control.
(CreationProperties.BrowserExecutableFolder) an pass some command line parameters to the control to activate WebGPU.

Now my question is, what is the best practice to access the underlying WebView2 Control?

In the sourcecode I found that it is possible to override the template

VisualTree = new FrameworkElementFactory(typeof(WebView2Control), webViewTemplateChildName)

Now my WPF skills are not the best but I tried this code:


xmlns:blazor="clr-namespace:Microsoft.AspNetCore.Components.WebView.Wpf;assembly=Microsoft.AspNetCore.Components.WebView.Wpf"
        xmlns:WpfWebView="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"

<blazor:BlazorWebView Grid.Row="1" x:Name="BlazorWebView" HostPage="wwwroot/index.html" Services="{StaticResource services}">
            <blazor:BlazorWebView.Template>
                <ControlTemplate x:Name="WebView" TargetType="WpfWebView:WebView2">
                    <WpfWebView:WebView2 DefaultBackgroundColor="Green"></WpfWebView:WebView2>
                </ControlTemplate>
            </blazor:BlazorWebView.Template>

I get the error that TargetType can only be of Control etc, but Microsoft.Web.WebView2.Wpf.WebView2 is only a FrameworkElement.

I only managed to get it to work with the following code in the code behind:
But is this the best practice? Is there a XAML way? Can there maybe a easier more intuitive way?

Can there be maybe a offical docs.microsoft

BlazorWebView.Template = new ControlTemplate()
            {
                // The BlazorWebView defines a control named WebView
                // Could not be done in xaml since control is just a FrameworkElement
                VisualTree = new FrameworkElementFactory(typeof(CustomWebView2), "WebView")
            };

public class CustomWebView2 : Microsoft.Web.WebView2.Wpf.WebView2
    {
        public CustomWebView2()
            : base()
        {
            this.CreationProperties.BrowserExecutableFolder = @"C:\Test\CanaryWebView\";
        }
    }

Also since changing the HostPage Property causes a Navigate() it seems impossible to set custom Environment settings
since calling EnsureCoreWebView2Async(customEnvSetting) is answered with the following exception: WebView2 was already initialized with a different CoreWebView2Environment. Check to see if the Source property was already set or EnsureCoreWebView2Async was previously called with different values. If I do not set HostPage after calling EnsureCoreWebView2Async() the exeption does not happen. Maybe related to this issue: MicrosoftEdge/WebView2Feedback#1782

It seems someting causes already a initialize or a double initialize in setting HostPage


            var env = CoreWebView2Environment.CreateAsync(null, null, new CoreWebView2EnvironmentOptions
            {
                AdditionalBrowserArguments = "--enable-features=enable-unsafe-webgpu",
            }).Result;
           CustomWebView2.EnsureCoreWebView2Async(env)

Thanks @Eilon ;)

Public API Changes

        <blazor:BlazorWebView.Template>
            <ControlTemplate x:Name="WebView" TargetType="WpfWebView:WebView2">
                <WpfWebView:WebView2 DefaultBackgroundColor="Green"></WpfWebView:WebView2>
            </ControlTemplate>
        </blazor:BlazorWebView.Template>

Intended Use-Case

Use Edge Canary Preview Build
Activate edge://flags like activating WebGPU

@MichaelPeter MichaelPeter changed the title Wpf BlazorWebView: WPF Documenation how access the underlying WebView to set additionalBrowserArguments or CreationProperties.BrowserExecutableFolder BlazorWebView for WPF Documenation how access the underlying WebView2 to set additionalBrowserArguments or CreationProperties.BrowserExecutableFolder Dec 26, 2021
@Eilon Eilon added area-blazor Blazor Hybrid / Desktop, BlazorWebView feature-blazor-windesktop Issues in Blazor in WPF or WinForms labels Dec 27, 2021
@Eilon
Copy link
Member

Eilon commented Dec 27, 2021

It would indeed be nice to support this; we'll have to think about the best way to support that that is easy to use.

@MichaelPeter
Copy link
Author

MichaelPeter commented Dec 27, 2021

So I think I found why this fails:

First of all, I cannot create a workarround for this since in the BlazorWebView.RequiredStartupPropertiesSet requires the HostPage property to be set to start up.

if (!RequiredStartupPropertiesSet || _webviewManager != null)

Now the BlazorWebView uses the Microsoft.AspNetCore.Components.WebView.WebView2WebViewManager.Navigate()
this one explicitily initializes the WebView2 - which then results in the error:

See the await _webview.EnsureCoreWebView2Async(); in the WebView2WebViewManager.InitializeWebView2()

Since this method is called explicitly calling EnsureCoreWebView2Async myself beforehand causes an exception when the WebView2WebViewManager calls the method, if I call it afterwards the WebView2WebViewManager has initalized the view already.

grafik

This is a showstopper for me and prevents any customizations of the WebView2 enviroment with BlazorWebView.

@Eilon
Copy link
Member

Eilon commented Dec 28, 2021

@MichaelPeter right, I think the ultimate fix for this will be to expose some kind of event where anyone can handle that event and provide additional startup info to the WebView2. That should be much easier than trying to override various internal behaviors of the BlazorWebView.

I'm imagining something like this:

blazorWebView1.InitializingWebView += MyInitHandler;

...

void MyInitHandler(object sender, WebViewInitEventArgs e)
{
    e.CoreWebView2EnvironmentOptions.AdditionalBrowserArguments = "--enable-features=enable-unsafe-webgpu";
}

And the control will call your event handler at the right time in the lifecycle.

@MichaelPeter
Copy link
Author

MichaelPeter commented Dec 29, 2021

Hello @Eilon,

was also thinking about it, I think that works.

It would just be importaint that when the event is called the BlazorWebView.WebView is already set.

For example that the browser binaries can also be setted or other things which are not yet considered.
Also subscribing to events before the first page load, or if it should be reacted on events during the pageload.

The BlazorWebView.WebView.CreationProperties like BrowserExecutableFolder or UserDataFolder are considereded right?

grafik

void MyInitHandler(object sender, WebViewInitEventArgs e)
{
    blazorWebView1.WebView.CreationProperties.BrowserExecutableFolder  = "<MyBinariesPath>"
    blazorWebView1.WebView.WebMessageReceived += CustomEventHandler...
    e.CoreWebView2EnvironmentOptions.AdditionalBrowserArguments = "--enable-features=enable-unsafe-webgpu";
}

Thank you!

@Eilon
Copy link
Member

Eilon commented Dec 29, 2021

Yeah I think whatever event(s) we would expose would give you access to the objects so that you can do any extra custom work you need to. For example, let's say right after the WebView2 is created, or when CoreWebView2 becomes available, we could raise an event so that the handler could do whatever they want with it (set properties, hook events, etc.).

@MichaelPeter
Copy link
Author

Would you accept a pull request regarding this?

@MichaelPeter
Copy link
Author

MichaelPeter commented Jan 16, 2022

I created a commit in a fork for a sample implementation for WPF, if this would be acceptable I could create a
version for WinForms and make a pull request.

MichaelPeter@12590f4
Edit: Fixed a bug and added code to the WPF sample in the branch: MichaelPeter@4b54158

@MichaelPeter
Copy link
Author

MichaelPeter commented Feb 23, 2022

@Eilon If I would add the feature also for winforms, would the team accept a pull request?

@mkArtakMSFT
Copy link
Member

Closing this as a dupe of #5512

@mkArtakMSFT mkArtakMSFT added the s/duplicate 2️⃣ This issue or pull request already exists label Apr 1, 2022
@ghost ghost locked as resolved and limited conversation to collaborators May 1, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Blazor Hybrid / Desktop, BlazorWebView feature-blazor-windesktop Issues in Blazor in WPF or WinForms proposal/open s/duplicate 2️⃣ This issue or pull request already exists
Projects
None yet
Development

No branches or pull requests

3 participants