diff --git a/src/Controls/samples/Controls.Sample/Pages/Controls/WebViewPage.xaml b/src/Controls/samples/Controls.Sample/Pages/Controls/WebViewPage.xaml
index 06240032d8bb..e9ee83d3b1c0 100644
--- a/src/Controls/samples/Controls.Sample/Pages/Controls/WebViewPage.xaml
+++ b/src/Controls/samples/Controls.Sample/Pages/Controls/WebViewPage.xaml
@@ -12,6 +12,7 @@
Text="HtmlWebViewSource (String)"
Style="{StaticResource Headline}"/>
@@ -31,6 +32,9 @@
+
diff --git a/src/Controls/samples/Controls.Sample/Pages/Controls/WebViewPage.xaml.cs b/src/Controls/samples/Controls.Sample/Pages/Controls/WebViewPage.xaml.cs
index 3fe6680a9ced..7696658c333c 100644
--- a/src/Controls/samples/Controls.Sample/Pages/Controls/WebViewPage.xaml.cs
+++ b/src/Controls/samples/Controls.Sample/Pages/Controls/WebViewPage.xaml.cs
@@ -28,6 +28,14 @@ protected override void OnDisappearing()
MauiWebView.Navigated -= OnMauiWebViewNavigated;
}
+ void OnUpdateHtmlSourceClicked(object sender, EventArgs args)
+ {
+ Random rnd = new();
+ HtmlWebViewSource htmlWebViewSource = new();
+ HtmlSourceWebView.Source = htmlWebViewSource;
+ htmlWebViewSource.Html += $"
Updated Content {rnd.Next()}!
";
+ }
+
void OnGoBackClicked(object sender, EventArgs args)
{
Debug.WriteLine($"CanGoBack {MauiWebView.CanGoBack}");
diff --git a/src/Core/src/Platform/Windows/MauiWebView.cs b/src/Core/src/Platform/Windows/MauiWebView.cs
index a4028f258c39..0474da75ef3f 100644
--- a/src/Core/src/Platform/Windows/MauiWebView.cs
+++ b/src/Core/src/Platform/Windows/MauiWebView.cs
@@ -99,11 +99,16 @@ public async void LoadHtml(string? html, string? baseUrl)
NavigateToString(!string.IsNullOrEmpty(htmlWithBaseTag) ? htmlWithBaseTag : html);
// Free up memory after we're done with _internalWebView
- _internalWebView = null;
+ if (_internalWebView.IsValid())
+ {
+ _internalWebView.Close();
+ _internalWebView = null;
+ }
};
// Kick off the initial navigation
- _internalWebView.NavigateToString(html);
+ if (_internalWebView.IsValid())
+ _internalWebView.NavigateToString(html);
}
public async void LoadUrl(string? url)
diff --git a/src/Core/src/Platform/Windows/WebViewExtensions.cs b/src/Core/src/Platform/Windows/WebViewExtensions.cs
index 667b04322652..c22b1c6d1a7e 100644
--- a/src/Core/src/Platform/Windows/WebViewExtensions.cs
+++ b/src/Core/src/Platform/Windows/WebViewExtensions.cs
@@ -1,5 +1,4 @@
using System;
-using System.Threading.Tasks;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.Maui.Platform
@@ -80,5 +79,17 @@ public static void EvaluateJavaScript(this WebView2 webView, EvaluateJavaScriptA
{
request.RunAndReport(webView.ExecuteScriptAsync(request.Script));
}
+
+ internal static bool IsValid(this WebView2 webView)
+ {
+ try
+ {
+ return webView is not null && webView.CoreWebView2 is not null;
+ }
+ catch (Exception ex) when (ex is ObjectDisposedException || ex is InvalidOperationException)
+ {
+ return false;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/Core/tests/DeviceTests/Handlers/WebView/WebViewHandlerTests.Windows.cs b/src/Core/tests/DeviceTests/Handlers/WebView/WebViewHandlerTests.Windows.cs
index 909237121303..bcbe7e8d8e5c 100644
--- a/src/Core/tests/DeviceTests/Handlers/WebView/WebViewHandlerTests.Windows.cs
+++ b/src/Core/tests/DeviceTests/Handlers/WebView/WebViewHandlerTests.Windows.cs
@@ -1,4 +1,6 @@
-using System.Threading.Tasks;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Maui.Controls;
using Microsoft.Maui.DeviceTests.Stubs;
@@ -9,6 +11,52 @@ namespace Microsoft.Maui.DeviceTests
{
public partial class WebViewHandlerTests
{
+ [Theory(DisplayName = "UrlSource Updates Correctly")]
+ [InlineData("Old Source
", "New Source
\"")]
+ [InlineData("Old Source
", "New Source
\"")]
+ public async Task HtmlSourceUpdatesCorrectly(string oldSource, string newSource)
+ {
+ var pageLoadTimeout = TimeSpan.FromSeconds(2);
+
+ await InvokeOnMainThreadAsync(async () =>
+ {
+ var webView = new WebViewStub()
+ {
+ Width = 100,
+ Height = 100,
+ Source = new HtmlWebViewSourceStub { Html = oldSource }
+ };
+
+ var handler = CreateHandler(webView);
+
+ var platformView = handler.PlatformView;
+
+ // Setup the view to be displayed/parented and run our tests on it
+ await platformView.AttachAndRun(async () =>
+ {
+ // Wait for the page to load
+ var tcsLoaded = new TaskCompletionSource();
+ var ctsTimeout = new CancellationTokenSource(pageLoadTimeout);
+ ctsTimeout.Token.Register(() => tcsLoaded.TrySetException(new TimeoutException($"Failed to load HTML")));
+
+ webView.NavigatedDelegate = (evnt, url, result) =>
+ {
+ // Set success when we have a successful nav result
+ if (result == WebNavigationResult.Success)
+ tcsLoaded.TrySetResult(result == WebNavigationResult.Success);
+ };
+
+ // Load the new Source
+ webView.Source = new HtmlWebViewSourceStub { Html = newSource };
+
+ handler.UpdateValue(nameof(IWebView.Source));
+
+ // If the new source is loaded without exceptions, the test has passed
+ Assert.True(await tcsLoaded.Task);
+ });
+ });
+ }
+
[Fact(DisplayName = "Closing Window With WebView Doesnt Crash")]
public async Task ClosingWindowWithWebViewDoesntCrash()
{
diff --git a/src/Core/tests/DeviceTests/Stubs/HtmlWebViewSourceStub.cs b/src/Core/tests/DeviceTests/Stubs/HtmlWebViewSourceStub.cs
new file mode 100644
index 000000000000..39ed9a347687
--- /dev/null
+++ b/src/Core/tests/DeviceTests/Stubs/HtmlWebViewSourceStub.cs
@@ -0,0 +1,12 @@
+namespace Microsoft.Maui.DeviceTests.Stubs
+{
+ class HtmlWebViewSourceStub : IWebViewSource
+ {
+ public string Html { get; set; }
+
+ public void Load(IWebViewDelegate webViewDelegate)
+ {
+ webViewDelegate.LoadHtml(Html, null);
+ }
+ }
+}