Skip to content

Feature/blazorwebview wpf composition control opt in - #34869

Merged
jfversluis merged 5 commits into
dotnet:net11.0from
mobiletonster:feature/blazorwebview-wpf-composition-control-opt-in
Jul 2, 2026
Merged

Feature/blazorwebview wpf composition control opt in#34869
jfversluis merged 5 commits into
dotnet:net11.0from
mobiletonster:feature/blazorwebview-wpf-composition-control-opt-in

Conversation

@mobiletonster

Copy link
Copy Markdown

Description of Change

This change introduces an opt‑out mechanism for using WebView2CompositionControl in WPF BlazorWebView scenarios.
While WebView2CompositionControl resolves the WPF airspace issue, it introduces measurable rendering overhead that
negatively impacts Razor component performance.

For apps that do not require XAML‑over‑WebView layering, developers can now disable the composition control and fall
back to the standard WebView2, resulting in significantly improved performance on WPF.

This feature also addresses feedback from the original WebView2CompositionControl introduction
(PR #31777: #31777)
and community requests asking for an opt‑in/opt‑out toggle
(Issue #28063: #28063).


Issues Fixed / Related

This PR enables opting out of WebView2CompositionControl (added in .NET 10.0 to address WPF airspace issues) in
favor of the standard WebView2 when airspace layering is unnecessary and lower rendering overhead is preferred.


Summary of Changes

  • Added UseCompositionControl dependency property (default: true) on BlazorWebView, preserving existing
    behavior.
  • Updated _webview and the WebView property to use IWebView2, implemented by both WebView2 and
    WebView2CompositionControl.
  • CreateWebViewTemplate() now selects the correct control type at initialization; the property‑changed callback
    updates the template if changed before the control is added to the visual tree.
  • Added an InvalidOperationException if UseCompositionControl is modified after the underlying WebView has been
    created.
  • Updated WebView2WebViewManager and BlazorWebViewInitializedEventArgs shared source to use the WPF IWebView2
    alias.
  • Updated PublicAPI.Unshipped.txt with *REMOVED* entries for the old WebView2CompositionControl return types
    and the new IWebView2 and UseCompositionControl public API surface.

PR Review Feedback Addressed

  • Missing *REMOVED* entries in PublicAPI.Unshipped.txt — Added *REMOVED* entries for both
    BlazorWebViewInitializedEventArgs.WebView and BlazorWebView.WebView to satisfy the API analyzer.
  • Unsafe cast in OnApplyTemplate() — Replaced the direct (IWebView2) cast with an is not pattern match that
    throws a descriptive InvalidOperationException if the template child is missing or the wrong type.
  • Unit tests — No WPF-specific test project exists in this repository; the existing DeviceTests project targets
    the MAUI handler layer and is not appropriate for standalone WPF control tests. A dedicated WPF test project would be
    a disproportionate investment for this change and has been deferred.
  • WebView return type / source compatibility — The change from WebView2CompositionControl! to IWebView2! is
    intentional and documented. The proposed alternative (keeping WebView as WebView2CompositionControl? and adding a
    WebViewBase property) would itself be a breaking change (nullable return) and would produce a confusing two-property
    API. Callers relying on WebView2CompositionControl-specific members can cast explicitly.

Notes

This is not a bug fix; it is a feature/performance enhancement.

Copilot AI review requested due to automatic review settings April 8, 2026 00:06
@github-actions

github-actions Bot commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34869

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34869"

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a WPF-specific toggle to allow opting out of WebView2CompositionControl for BlazorWebView, enabling better performance in scenarios that don’t need XAML-over-WebView layering, while preserving the current default behavior.

Changes:

  • Added UseCompositionControl (default true) to select between WebView2CompositionControl and standard WebView2.
  • Updated the exposed WebView surface (and related initialization plumbing) to use a common WPF IWebView2 type.
  • Updated WPF PublicAPI tracking with new entries and *REMOVED* markers for the prior return types.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
src/BlazorWebView/src/Wpf/BlazorWebView.cs Adds UseCompositionControl DP, selects the appropriate WPF WebView2 control via template creation, and updates WebView to return IWebView2.
src/BlazorWebView/src/SharedSource/WebView2WebViewManager.cs Switches the WPF WebView2 alias to IWebView2 to support either underlying control.
src/BlazorWebView/src/SharedSource/BlazorWebViewInitializedEventArgs.cs Updates the WPF WebView event arg type alias to IWebView2.
src/BlazorWebView/src/Wpf/PublicAPI.Unshipped.txt Records new API surface and removals for the changed WebView-returning members.
@kubaflo

kubaflo commented Apr 26, 2026

Copy link
Copy Markdown
Collaborator

Code Review — PR #34869

Multi-model review (Claude Opus, GPT-5.4, Claude Sonnet 4.5)

Independent Assessment

What this changes: Adds a UseCompositionControl WPF dependency property (default: true) to BlazorWebView that lets developers opt out of WebView2CompositionControl in favor of the standard WebView2 for better rendering performance when WPF airspace layering is not needed. Internally, the _webview field and public WebView property are widened from the concrete WebView2CompositionControl type to the IWebView2 interface (which both controls implement).

Inferred motivation: WebView2CompositionControl was introduced in .NET 10 GA (PR #31777) to fix the WPF airspace issue, but it introduces measurable rendering overhead. Users who don't need XAML-over-WebView layering want to opt out.

Reconciliation with PR Narrative

Author claims: Feature enhancement, not a bug fix. Breaking change to WebView return type is intentional. No tests due to lack of WPF test infrastructure.

Agreement: The code matches the description accurately. The approach is sound — using IWebView2 as the common type is the cleanest path. The PR description is thorough and addresses prior review feedback.

Findings

⚠️ Warning — Branch target may be incorrect (needs maintainer guidance)

This PR targets net10.0, but .NET 10 GA shipped in November 2025 (commit e101f0d9ac marked the API as shipped Nov 3, 2025). The WebView2CompositionControl return types on BlazorWebView.WebView and BlazorWebViewInitializedEventArgs.WebView are in PublicAPI.Shipped.txt, making this a breaking change to shipped GA API.

Per repository conventions, new features with API changes should target the highest netN.0 feature branch (net11.0). This PR adds new public API surface (UseCompositionControl, UseCompositionControlProperty) and changes shipped return types — both are feature-branch work, not servicing.

Recommendation: A MAUI maintainer should confirm whether this should retarget to net11.0.

⚠️ Warning — Breaking API change to WebView property (binary + source)

BlazorWebView.WebView changes from WebView2CompositionControl!IWebView2! and BlazorWebViewInitializedEventArgs.WebView from WebView2CompositionControlIWebView2.

  • Binary breaking: Callers compiled against .NET 10 GA will get MissingMethodException at runtime
  • Source breaking: Code explicitly typed as WebView2CompositionControl (e.g., WebView2CompositionControl ctrl = blazorWebView.WebView;) won't compile

The *REMOVED* entries in PublicAPI.Unshipped.txt correctly track this against the shipped API — the Public API analyzer approach is sound. However, since these were shipped in .NET 10 GA, this needs explicit maintainer approval for the breaking change, with migration guidance in release notes.

Multi-model agreement: all 3 models flagged this. All agreed it's acceptable for a pre-GA change, but the shipped status in PublicAPI.Shipped.txt raises the bar.

💡 Suggestion — Missing newline at end of PublicAPI.Unshipped.txt

src/BlazorWebView/src/Wpf/PublicAPI.Unshipped.txt doesn't end with a newline. This will trigger git diff warnings and may cause analyzer issues.

Multi-model agreement: all 3 models flagged this.

💡 Suggestion — (_webview as IDisposable)?.Dispose() cast — verify necessity

In DisposeAsyncCore(), the dispose changed from _webview?.Dispose() to (_webview as IDisposable)?.Dispose(). If IWebView2 extends IDisposable, the cast is unnecessary. If it doesn't, the cast is correct and defensive. Either way it works, but a brief comment explaining the cast would help future readers.

💡 Suggestion — Binding to UseCompositionControl could throw unexpectedly

If a consumer data-binds UseCompositionControl and the bound value changes after the WebView is created, the property-changed callback throws InvalidOperationException. The XML docs correctly warn about this, but consider logging a warning instead of throwing for the "value didn't actually change" case (i.e., setting true when it's already true after initialization).

Devil's Advocate

Challenge to my findings: The branch target concern may be outdated if the team is still accepting feature work on net10.0 for a point release. MAUI has historically included features in servicing releases. A maintainer should weigh in.

Challenge to my approval: I can't verify runtime behavior of the WPF template swapping or IWebView2 interface contract without running the code on Windows. The WebView2 SDK's IWebView2 interface surface is an external dependency — if it changes or lacks expected members, this will break at runtime.

What I didn't verify: No WPF test infrastructure exists in this repo, so I can't empirically verify the UseCompositionControl=false path works correctly. The approach is sound in theory, but manual testing on WPF is essential before merge.

CI Status

CI checks show fail for maui-pr, maui-pr-devicetests, and maui-pr-uitests, but the failure links reference PR #34764 (a different PR), suggesting these may be base-branch failures rather than failures caused by this PR. Build Analysis is pending.

Verdict: NEEDS_DISCUSSION

Confidence: medium
Summary: The implementation is clean, well-documented, and follows correct patterns for WPF dependency properties. The core concern is that this makes a breaking change to shipped .NET 10 GA public API and targets a servicing branch (net10.0) rather than the feature branch (net11.0). A MAUI maintainer should confirm the branch target and approve the breaking API change. The code itself is well-structured — if the branch and breaking change are approved, the implementation is ready.

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please review the comment?

@mobiletonster

mobiletonster commented Apr 27, 2026 via email

Copy link
Copy Markdown
Author
@kubaflo

kubaflo commented Apr 27, 2026

Copy link
Copy Markdown
Collaborator

@mobiletonster no worries, it might be a bit confusing at first :) So the main branch is the latest maui release (currently net10), net10 branch is an old branch we had for net10 pre-releases. MauiBot asked you to target this pr to net11 branch. I've just done it;

@kubaflo
kubaflo changed the base branch from net10.0 to net11.0 April 27, 2026 18:21
@kubaflo

kubaflo commented Apr 27, 2026

Copy link
Copy Markdown
Collaborator

@mobiletonster I've also resolved conflicts :)

@kubaflo

kubaflo commented Apr 27, 2026

Copy link
Copy Markdown
Collaborator

Code Review — PR #34869 (Re-review post-retarget)

Previous Finding Status

# Finding Status
1 ⚠️ Branch target net10.0 — breaking change to shipped GA API Fixed — retargeted to net11.0 (feature branch). API changes are now for .NET 11, not servicing.
2 ⚠️ Breaking API change (WebView return type) Acceptable — in net11.0 this is a new-major-version API change, not a servicing break. *REMOVED* entries properly track the .NET 10 → 11 transition.
3 💡 Missing newline at EOF in PublicAPI.Unshipped.txt ⚠️ Still present\ No newline at end of file
4 💡 (_webview as IDisposable)?.Dispose() cast ℹ️ Non-blocking
5 💡 Binding to UseCompositionControl edge case ℹ️ Non-blocking, documented

Merge Conflict Resolution

Conflicts resolved by accepting net11.0 versions for 10 infrastructure files (NuGet.config, global.json, Version.Details.xml, etc.). None of the PR's BlazorWebView changes were affected — the core diff is identical to the pre-merge version.

CI Status

CI just started after the merge push. Build Analysis pending, maui-pr not yet triggered. No results to assess yet.

Verdict: LGTM

Confidence: high
Summary: The retarget from net10.0net11.0 resolves the primary concern from the initial review. The API change is now properly in the feature branch for .NET 11. Implementation is clean, well-documented, and follows correct WPF patterns. Only remaining nit is the missing EOF newline in PublicAPI.Unshipped.txt. Ready for maintainer approval.

mobiletonster and others added 5 commits April 27, 2026 20:29
Allows opting out of the WebView2CompositionControl (introduced in
net10.0 to fix WPF airspace issues) in favor of the standard WebView2
control when airspace layering is not required and lower rendering
overhead is preferred.

- Add UseCompositionControl dependency property (default: true) to
  BlazorWebView, preserving existing behavior by default
- Type _webview and the WebView property as IWebView2, the interface
  implemented by both WebView2 and WebView2CompositionControl
- CreateWebViewTemplate() selects the correct control type at init time;
  the property-changed callback swaps the template if set before the
  control is added to the visual tree
- Throw InvalidOperationException if UseCompositionControl is changed
  after the underlying WebView2 has already been created
- Update WebView2WebViewManager and BlazorWebViewInitializedEventArgs
  shared source to use IWebView2 for the WPF type alias
- Update PublicAPI.Shipped.txt to reflect the IWebView2 return types
  and new UseCompositionControl public API
…Unshipped.txt

I misunderstood how this was used. This should correct it.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Enhanced error reporting when WebView2 template child is missing
or of the wrong type. Updated public API to return IWebView2
instead of WebView2CompositionControl for greater abstraction.
@kubaflo
kubaflo force-pushed the feature/blazorwebview-wpf-composition-control-opt-in branch from c612109 to 543def2 Compare April 27, 2026 18:30
@kubaflo

kubaflo commented Apr 27, 2026

Copy link
Copy Markdown
Collaborator

@jfversluis the pr looks good! The only question is if we want it in net 11

@mobiletonster

mobiletonster commented Apr 27, 2026 via email

Copy link
Copy Markdown
Author
@kubaflo

This comment has been minimized.

@github-actions github-actions Bot added the s/agent-review-in-progress AI review is currently running for this PR label Jun 18, 2026

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expert Review — 2 findings

See inline comments for details.

@@ -1 +1,8 @@
#nullable enable
*REMOVED*~Microsoft.AspNetCore.Components.WebView.BlazorWebViewInitializedEventArgs.WebView.get -> Microsoft.Web.WebView2.Wpf.WebView2CompositionControl
*REMOVED*Microsoft.AspNetCore.Components.WebView.Wpf.BlazorWebView.WebView.get -> Microsoft.Web.WebView2.Wpf.WebView2CompositionControl!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[major] Public API Surface — This removes the shipped BlazorWebView.WebView getter returning WebView2CompositionControl and replaces it with an IWebView2 return type. Return-type widening is still a metadata/signature break for existing compiled WPF consumers, and the same compatibility issue applies to BlazorWebViewInitializedEventArgs.WebView. Prefer an additive API shape that preserves the existing concrete WebView2CompositionControl-facing API for compatibility and adds a neutral IWebView2/active-control property for the new standard WebView2 option.

/// the visual tree). Changing it after the underlying WebView2 has been created will throw an
/// <see cref="InvalidOperationException"/>.
/// </remarks>
public bool UseCompositionControl

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[moderate] Regression Prevention and Test Coverage — This new public WPF behavior has no detected regression coverage. Please add targeted coverage for the default UseCompositionControl=true path, the false path creating a standard Microsoft.Web.WebView2.Wpf.WebView2, the initialized event/control property type exposed in each mode, and the documented late-change exception after the template child has been created.

@MauiBot MauiBot added s/agent-fix-win AI found a better alternative fix than the PR s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Jun 18, 2026

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI Review Summary

@mobiletonster — new AI review results are available based on this last commit: 543def2. To request a fresh review after new comments or commits, comment /review rerun.

Gate Skipped Code Review In Review Confidence Low Platform Windows Wpf Blazorwebview

Review Sessions — click to expand
Gate — Test Before & After Fix

Gate Result: ⚠️ SKIPPED

No tests were detected in this PR.

Recommendation: Add tests to verify the fix using the write-tests-agent.


Pre-Flight — Context & Validation

Issue: #28063 - WPF BlazorWebView WebView2CompositionControl airspace/performance follow-up
PR: #34869 - Feature/blazorwebview wpf composition control opt in
Platforms Affected: Windows WPF BlazorWebView (WEBVIEW2_WPF)
Files Changed: 4 implementation/API, 0 test

Key Findings

  • PR adds UseCompositionControl to WPF BlazorWebView, defaulting to true so existing airspace behavior remains the default while allowing standard WebView2 opt-out for performance.
  • WPF WebView-related public/internal types are widened from WebView2CompositionControl to IWebView2 so both WPF WebView2 controls can flow through the existing manager and initialized event args.
  • No tests are included; gate was already skipped because no tests were detected in the PR.
  • GitHub CLI is unauthenticated in this environment, so PR context came from local review branch and public GitHub API responses.

Code Review Summary

Verdict: NEEDS_DISCUSSION
Confidence: low
Errors: 0 | Warnings: 2 | Suggestions: 1

Key code review findings:

  • ⚠️ Public API return-type break still needs explicit maintainer/API approval: BlazorWebView.WebView and BlazorWebViewInitializedEventArgs.WebView change from WebView2CompositionControl to IWebView2.
  • ⚠️ CI status is undetermined from this unauthenticated environment, so LGTM is not appropriate under the review rules.
  • 💡 Consider release-note/migration documentation for callers that need concrete WebView2CompositionControl members and must cast.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #34869 Add UseCompositionControl DP, choose WebView2CompositionControl vs WebView2 in the template, and expose WPF webview as IWebView2. ⚠️ Gate skipped (no tests detected) BlazorWebView.cs, shared WebView2 source, PublicAPI Original PR; default preserves existing behavior but changes public return type.

Code Review — Deep Analysis

Code Review — PR #34869

Independent Assessment

What this changes: Adds a WPF BlazorWebView.UseCompositionControl dependency property, defaulting to true, to choose between WebView2CompositionControl and standard WebView2. The WPF internal/public webview type is widened to Microsoft.Web.WebView2.Wpf.IWebView2, and PublicAPI entries record the return-type change plus new property/API surface.

Inferred motivation: Preserve the airspace-fixing composition control by default while allowing WPF apps that do not need XAML-over-WebView layering to opt out for better rendering performance.

Reconciliation with PR Narrative

Author claims: This is a feature/performance enhancement, not a bug fix; it intentionally changes WPF WebView-related API from WebView2CompositionControl to IWebView2; tests are deferred because there is no dedicated WPF test project.

Agreement/disagreement: The code matches the narrative. UseCompositionControlProperty defaults to true (BlazorWebView.cs:93-97), the constructor creates the template from the current value (BlazorWebView.cs:127-129), the template selects the concrete WPF control (BlazorWebView.cs:248-253), and shared WebView2 plumbing now aliases WPF to IWebView2 (BlazorWebViewInitializedEventArgs.cs:8, WebView2WebViewManager.cs:31). The only remaining discussion point is API compatibility/approval for changing a shipped return type to an interface, plus the current red/undetermined CI state.

Prior Review Reconciliation

Prior ❌ Error Finding Source Status Evidence
No prior ❌ Error findings found. N/A N/A Queried public PR issue comments and inline review comments; gh review surfaces were unavailable because the CLI is unauthenticated. Prior reviews found warnings/discussion only, primarily branch target/API break and CI validation.

Notes:

  • Earlier branch-target warning is fixed; the PR now targets net11.0.
  • Earlier missing newline nit appears obsolete; the current PublicAPI.Unshipped.txt content read from HEAD ends with newline.
  • Prior API design discussion about IWebView2 remains a maintainer/API review concern, not a concrete code defect.

Blast Radius Assessment

  • Runs for all instances: Yes, for WPF BlazorWebView instances. The constructor now always creates a template through CreateWebViewTemplate(...), but the default remains composition control, preserving current runtime behavior unless consumers opt out.
  • Startup impact: Yes, this affects WPF BlazorWebView initialization/template application. The default path still creates WebView2CompositionControl.
  • Static/shared state: No new static mutable/shared state. The new dependency property metadata is static, but instance state remains per-control.

CI Status

  • Required-check result: gh pr checks 34869 --repo dotnet/maui --required could not run because gh is unauthenticated (gh_exit=4).
  • Classification: Undetermined from this environment. Public check-run/comment context indicates CI was not fully validated or had failures at different points, but authenticated AzDO detail is unavailable.
  • Action taken: Confidence capped to low and verdict cannot be LGTM.

Findings

❌ Error

No code-level ❌ Error findings found on the added/modified lines.

⚠️ Warning — Public API return-type break still needs explicit approval

BlazorWebView.WebView changes from WebView2CompositionControl! to IWebView2! (BlazorWebView.cs:135-144; PublicAPI entries at PublicAPI.Unshipped.txt:2-8), and BlazorWebViewInitializedEventArgs.WebView similarly changes to IWebView2 (BlazorWebViewInitializedEventArgs.cs:8, :30-32). This is intentional and correctly tracked, and targeting net11.0 makes it much more plausible than servicing, but consumers typed directly against WebView2CompositionControl will need casts or source changes. This should have explicit API/maintainer sign-off.

⚠️ Warning — CI is red/undetermined from this environment

The changed code is WPF BlazorWebView-only, but without authenticated required-check/AzDO details I cannot classify current CI state as passing or unrelated. Per review rules, this blocks LGTM.

💡 Suggestion — Consider documenting the IWebView2 cast expectation

The API docs correctly state the inner control may be either WebView2CompositionControl or WebView2Control (BlazorWebView.cs:135-142, :211-219). Given reviewer concern that IWebView2 is not the most ergonomic consumer type, release notes or migration docs should call out that callers needing concrete-specific members must cast based on UseCompositionControl.

Failure-Mode Probing

  • UseCompositionControl=false before initialization: The property-changed callback updates Template while _webview is still null (BlazorWebView.cs:237-245), so OnApplyTemplate creates/accepts the standard WebView2 through IWebView2.
  • UseCompositionControl changes after template/webview creation: The callback throws InvalidOperationException once _webview != null (BlazorWebView.cs:239-243), matching the XML docs.
  • Custom template omits or misnames the child: OnApplyTemplate now throws a descriptive InvalidOperationException instead of an invalid cast/null failure (BlazorWebView.cs:280-286).
  • Shared manager/event args with either concrete WPF control: Both WPF aliases now use IWebView2 (WebView2WebViewManager.cs:31, BlazorWebViewInitializedEventArgs.cs:8).
  • Disposal after widening to interface: The code disposes only when the interface instance is also IDisposable (BlazorWebView.cs:450), avoiding a compile-time dependency on IWebView2 inheriting IDisposable.

Verdict: NEEDS_DISCUSSION

Confidence: low
Summary: The implementation is clean and I found no concrete code defect. However, the change deliberately alters shipped public API shape and CI status is undetermined from this unauthenticated environment, so this needs maintainer/API sign-off and CI clarification before merge.


Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix-1 Preserve existing concrete WPF WebView APIs and add a new neutral IWebView2 WebViewControl access path plus UseCompositionControl. ✅ PASS — targeted WPF build succeeded 4 files Better API compatibility than PR because it avoids widening existing public return types; tradeoff is two access properties and a legacy property that throws in opt-out mode.
2 try-fix-2 Add a separate standard-WebView2 WPF BlazorWebView control type while leaving existing BlazorWebView unchanged. ❌ FAIL — rejected before implementation 0 files Too invasive: requires broad WPF control refactor and new public control API.
PR PR #34869 Add UseCompositionControl, select WebView2 control type in the template, and widen existing WPF WebView APIs to IWebView2. ⚠️ Gate skipped (no tests detected) 4 files Clean and compact, but has deliberate public return-type break needing API approval.

Cross-Pollination

Model Round New Ideas? Details
maui-expert-reviewer 1 Yes Additive compatibility API: keep existing concrete WebView APIs and add neutral IWebView2 access. Implemented as try-fix-1.
maui-expert-reviewer 2 Yes Split standard WebView2 into a separate WPF control type. Rejected as too invasive for this PR.

Exhausted: Yes — the remaining meaningful alternatives either match the PR's current bool/interface strategy, try-fix-1's additive compatibility strategy, or require the broad separate-control refactor rejected in try-fix-2.
Selected Fix: Candidate #1 — It passed the targeted WPF build and most directly addresses the main review concern (public API return-type break). However, because there are no PR tests and only targeted build validation was possible, this should be treated as a candidate for maintainer/API discussion rather than an automatically superior merge recommendation.


Report — Final Recommendation

Comparative Report — PR #34869

Candidates compared

Rank Candidate Regression/build result Assessment
1 pr-plus-reviewer PASS — targeted WPF build succeeded in sandbox after restore Best candidate. It preserves the PR's opt-out behavior and default composition mode while applying the expert reviewer's major compatibility feedback by keeping existing concrete WPF APIs and adding a neutral IWebView2 access path.
2 try-fix-1 PASS — targeted WPF build succeeded Technically the same additive compatibility strategy as pr-plus-reviewer, and therefore also stronger than the raw PR. Ranked below pr-plus-reviewer only because the requested Phase 1 candidate explicitly incorporates the expert review findings into the PR-fix line.
3 pr Gate skipped — no tests detected; CI unavailable/undetermined in this environment Compact implementation and likely functionally correct, but it widens existing public WPF return types from WebView2CompositionControl to IWebView2, creating a source/binary compatibility concern that the expert reviewer flagged as major.
4 try-fix-2 FAIL — rejected before implementation The separate-control design has good theoretical compatibility, but it is too invasive for this PR and would require broad WPF control refactoring and new API design approval. Per the ranking rule, failed candidates rank below passing candidates.

Key comparison points

pr and pr-plus-reviewer both keep the requested user-facing behavior: WPF BlazorWebView uses WebView2CompositionControl by default and allows opting out to standard WebView2 for performance-sensitive scenarios where airspace layering is unnecessary.

The decisive difference is public API compatibility. The raw PR changes the existing WebView property return types to IWebView2, which is a breaking metadata/signature change for consumers compiled against WebView2CompositionControl. pr-plus-reviewer avoids that break by preserving the concrete APIs and adding WebViewControl for the selected active WPF control. This is more awkward than the raw PR because callers now have two access paths, and the legacy WebView property can throw if used after opting out, but that behavior is limited to callers who explicitly select the new standard-WebView2 mode.

Test coverage remains the main weakness for the winning candidate. The gate was skipped because no tests were detected in the PR, and no automated regression test candidate was available from STEP 5a. However, candidates with passing targeted builds and no known regression-test failure must rank above failed/rejected candidates, and pr-plus-reviewer addresses the only major code-review finding while preserving the PR's intended behavior.

Winner

pr-plus-reviewer wins. It is the best balance of behavior, compatibility, and implementation scope: it keeps the PR's opt-in performance improvement, avoids the major public API return-type break, and passed the targeted WPF build in the sandbox.


Future Action — review latest findings

No alternative fix was selected for this run. Review the session findings and CI results before merging.

@MauiBot MauiBot removed the s/agent-review-in-progress AI review is currently running for this PR label Jun 18, 2026
@kubaflo

kubaflo commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

🔍 AI-generated comment (drafted by GitHub Copilot CLI on behalf of @kubaflo)

@jfversluis — this one needs an owner decision to unblock; it's been waiting since April.

What it is: adds UseCompositionControl (default true) to WPF BlazorWebView so apps can opt out of WebView2CompositionControl (shipped .NET 10 GA via #31777) back to plain WebView2 for better perf. Completes the second half of #28063 (15 👍), which asked for the composition control "as the new default or as an option to select."

The open design question (from @mattleibow): to return either control, the public WebView getter changes from WebView2CompositionControl → the IWebView2 interface. Matt's concern: "IWebView2 is a very weird type — not a view type — so all existing code will have to cast." That's a permanent ergonomics regression on a GA API. His alternative was a compile-time handler swap (CollectionView-style), with the hedge "maybe this is fine if usage is lower."

Two realistic paths:
Accept it — the IWebView2 break is allowed on net11 (new major; *REMOVED* entries are correct), low usage, ship after a green CI run. Pragmatic.
Rework — keep a real view-typed accessor / do the handler swap. Cleaner API, more work for a narrow audience.

Caveats either way: narrow audience (WPF BlazorWebView + no airspace layering + perf-sensitive); no test coverage (no WPF test project exists); CI has never gone green here; perf claim is unquantified.

● Go/no-go for net11? And if go — accept the IWebView2 break, or rework per Matt's suggestion?

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please check the ai's suggestions?

@mobiletonster

mobiletonster commented Jun 30, 2026

Copy link
Copy Markdown
Author

Could you please check the ai's suggestions?

I saw the AI's suggestion. I think the impact of this change (as is) will be very minor if any at all. 1) The WPF Blazor web view is probably not widely used today 2) the probability that someone is trying to access the webview2 control from the parent of the BlazorWebView control is relatively unlikely. If they are, the fix is a pretty simple cast from IWebView2 -> Concrete type. I feel like given the statical probability of these conditions; it doesn't rise to the level of requiring more code to work around it.

However, if the humans believe otherwise, I think we could add the additional code for it.

@jfversluis
jfversluis merged commit 88504d8 into dotnet:net11.0 Jul 2, 2026
197 of 219 checks passed
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

🚨 API change(s) detected @davidbritch FYI

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

🚨 API change(s) detected @davidortinau FYI

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

community ✨ Community Contribution s/agent-fix-win AI found a better alternative fix than the PR s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) t/breaking 💥

6 participants