Skip to content
This repository has been archived by the owner on Oct 29, 2024. It is now read-only.

Changes to .NET 6 WPF BlazorWebView startup #333

Open
wants to merge 1 commit into
base: dotnet6
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 59 additions & 15 deletions src/Microsoft.MobileBlazorBindings.WPFNew/BlazorWebView.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
Expand All @@ -12,49 +11,94 @@ namespace Microsoft.MobileBlazorBindings.WPFNew
{
public sealed class BlazorWebView : Control, IDisposable
{
public static readonly DependencyProperty HostPageProperty = DependencyProperty.Register(
name: nameof(HostPage),
propertyType: typeof(string),
ownerType: typeof(BlazorWebView),
typeMetadata: new PropertyMetadata(OnHostPagePropertyChanged));

public static readonly DependencyProperty RootComponentsProperty = DependencyProperty.Register(
name: nameof(RootComponents),
propertyType: typeof(ObservableCollection<RootComponent>),
ownerType: typeof(BlazorWebView));

public static readonly DependencyProperty ServicesProperty = DependencyProperty.Register(
name: nameof(Services),
propertyType: typeof(IServiceProvider),
ownerType: typeof(BlazorWebView),
typeMetadata: new PropertyMetadata(OnServicesPropertyChanged));


private const string webViewTemplateChildName = "WebView";
private WebView2 _webView2;
private WebView2BlazorWebViewCore _core;

public BlazorWebView()
{
SetValue(RootComponentsProperty, new ObservableCollection<RootComponent>());
RootComponents.CollectionChanged += (_, ___) => StartWebViewCoreIfPossible();

Template = new ControlTemplate
{
VisualTree = new FrameworkElementFactory(typeof(WebView2), webViewTemplateChildName)
};
}

public string HostPage { get; set; }

public static readonly DependencyProperty RootComponentsProperty = DependencyProperty.Register(
nameof(RootComponents),
typeof(ObservableCollection<RootComponent>),
typeof(BlazorWebView));
public string HostPage
{
get { return (string)GetValue(HostPageProperty); }
set { SetValue(HostPageProperty, value); }
}

public ObservableCollection<RootComponent> RootComponents
=> (ObservableCollection<RootComponent>)GetValue(RootComponentsProperty);

public static readonly DependencyProperty ServicesProperty = DependencyProperty.Register(
nameof(Services),
typeof(IServiceProvider),
typeof(BlazorWebView));

public IServiceProvider Services
{
get { return (IServiceProvider)GetValue(ServicesProperty); }
set { SetValue(ServicesProperty, value); }
}

private static void OnServicesPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((BlazorWebView)d).OnServicesPropertyChanged(e);

private void OnServicesPropertyChanged(DependencyPropertyChangedEventArgs e) => StartWebViewCoreIfPossible();

private static void OnHostPagePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((BlazorWebView)d).OnHostPagePropertyChanged(e);

private void OnHostPagePropertyChanged(DependencyPropertyChangedEventArgs e) => StartWebViewCoreIfPossible();

private bool RequiredStartupPropertiesSet =>
_webView2 != null &&
HostPage != null &&
(RootComponents?.Any() ?? false) &&
Services != null;

protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);

StartWebViewCoreIfPossible();
}

public override void OnApplyTemplate()
{
base.OnApplyTemplate();

var webview = (WebView2)GetTemplateChild(webViewTemplateChildName);
_webView2 = (WebView2)GetTemplateChild(webViewTemplateChildName);

StartWebViewCoreIfPossible();
}

private void StartWebViewCoreIfPossible()
{
if (!RequiredStartupPropertiesSet)
{
return;
}

// TODO: Can OnApplyTemplate get called multiple times? Do we need to handle this more efficiently?
// TODO: Can this get called multiple times, such as from OnApplyTemplate or a property change? Do we need to handle this more efficiently?
_core?.Dispose();
_core = new WebView2BlazorWebViewCore(webview, Services, WPFDispatcher.Instance, HostPage);
_core = new WebView2BlazorWebViewCore(_webView2, Services, WPFDispatcher.Instance, HostPage);

// TODO: Consider respecting the observability of this collection
var addRootComponentTasks = RootComponents.Select(
Expand Down