Skip to content

Remove MAUI internal API usage#3251

Open
jfversluis wants to merge 17 commits into
mainfrom
jfversluis-toolkit-internals-audit
Open

Remove MAUI internal API usage#3251
jfversluis wants to merge 17 commits into
mainfrom
jfversluis-toolkit-internals-audit

Conversation

@jfversluis

Copy link
Copy Markdown
Member

Description of Change

Removes CommunityToolkit.Maui dependencies on MAUI internal APIs and implementation details so dotnet/maui can remove the InternalsVisibleTo entries for CommunityToolkit.Maui in .NET 11.

This migrates the toolkit to public MAUI APIs or toolkit-owned replacements across AvatarView, AppTheme helpers, Image/Touch behaviors, Gravatar image loading, StateContainer, Expander, IconTintColorBehavior, Keyboard/SemanticOrder helpers, WrapperControl, MediaElement controller lookup, and related tests.

This should be safe to merge ahead of .NET 11: the changes do not intentionally use .NET 11-specific APIs, and the package projects were restored/built successfully for net10.0 against the repo default MAUI 10 package version (10.0.60). Getting this merged before .NET 11 lands should let users upgrade from day 1 once dotnet/maui removes the IVTs.

Maintainer note: this touches behavior-sensitive areas where the toolkit previously depended on MAUI implementation details. Toolkit maintainers/reviewers should own the final correctness and compatibility validation before merging, especially for platform/runtime behavior that cannot be fully proven from this Windows environment.

Linked Issues

PR Checklist

Additional information

Validation performed:

  • Deep scans for MAUI internals/private reflection after the migration:
    • Microsoft.Maui.(Controls.)?Internals, .Internals., Internals., AppThemeBinding
    • IElementController, NavigationProxy, IShellSectionController, FontElement, TextElement, ImageElement, StreamWrapper, IResourcesProvider, InvalidateMeasureInternal, InvalidationTrigger, TryGetValueAndSource
    • GetField(, GetProperty(, GetMethod(, BindingFlags
  • dotnet restore src\CommunityToolkit.Maui.slnx --no-cache
  • dotnet build src\CommunityToolkit.Maui.slnx --no-restore -v minimal
  • dotnet build src\CommunityToolkit.Maui\CommunityToolkit.Maui.csproj -c Release -f net10.0 --no-restore
  • Package project builds for net10.0 against MAUI 10.0.60:
    • CommunityToolkit.Maui.Core
    • CommunityToolkit.Maui
    • CommunityToolkit.Maui.Camera
    • CommunityToolkit.Maui.MediaElement
    • CommunityToolkit.Maui.Maps
  • Focused tests:
    • AppThemeTests
    • AvatarViewInterfaceTests
    • ImageTouchBehaviorTests
    • TouchBehaviorTests
  • Analyzer/source-generator projects built successfully.
  • Downstream validation against dotnet/maui PR #34070 package artifacts (11.0.0-ci.pr34070.6.26324.9) passed for feasible package builds on this machine.

Environment limitations:

  • Full .NET 11 template/smoke validation requires a .NET 11-capable MAUI workload environment. This machine has a .NET 10 MAUI workload, so runtime/template smoke testing against the PR packages was blocked by workload/template mismatch rather than toolkit internal API usage.
  • The AppThemeObject<T>.GetBinding() targetless overload cannot fully preserve DynamicResourceExtension values using public MAUI APIs because binding converters do not expose the target BindableProperty. The target-aware toolkit extension methods and AppThemeResourceExtension preserve dynamic-resource behavior where the target property is available.

Copilot AI review requested due to automatic review settings June 24, 2026 10:36
@jfversluis

Copy link
Copy Markdown
Member Author

Follow-up verification after cross-checking #3097 item-by-item:

  • RequireFontManager() was still present in Snackbar.android.cs and UIFontExtensions.macios.cs after the initial PR push. This was missed because it is an internal MAUI extension method that does not live under an Internals namespace and still compiles against normal MAUI 10 packages while IVT is present.
  • Fixed in commit 4a55579f by replacing both calls with public Application.Current?.Handler?.MauiContext?.Services font-manager resolution.
  • Re-ran an exact scan for all APIs named in [.NET 11] Migrate off internal MAUI APIs before InternalsVisibleTo removal #3097:
    • RequireFontManager, InvalidateMeasureInternal, InvalidationTrigger, GetDefaultFontSize, AppThemeBinding, FontElement, TextElement, ImageElement, IResourcesProvider, StreamWrapper, ImageSource.CancellationTokenSource, and the internal XamlParseException(string, IServiceProvider) shape.
    • Result: no matches.
  • Also re-ran broader MAUI-internals/private-reflection scans. Only remaining BindingFlags.NonPublic usage is in toolkit unit tests reflecting toolkit-owned members.
  • Additional focused builds after the font-manager fix:
    • CommunityToolkit.Maui net10.0: passed.
    • CommunityToolkit.Maui net10.0-android: passed, existing platform analyzer warnings only.
    • CommunityToolkit.Maui net10.0-maccatalyst: passed, existing platform/obsolete warnings only.

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

Removes .NET MAUI internal API / implementation-detail dependencies across CommunityToolkit.Maui so MAUI can drop InternalsVisibleTo for the toolkit in .NET 11, using public MAUI APIs or toolkit-owned replacements instead.

Changes:

  • Reworks AppTheme binding/resource resolution and adds a toolkit dispatcher helper to avoid internal XAML/dispatcher APIs.
  • Migrates multiple controls/behaviors (e.g., AvatarView, Touch/ImageTouch, IconTintColor, SemanticOrderView, Keyboard helpers) off internal MAUI interfaces/properties.
  • Updates MediaElement iOS/macOS controller discovery to avoid internal handler/controller access; adjusts and expands unit tests accordingly.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/CommunityToolkit.Maui/Views/WrapperControl.windows.cs Removes internal handler access for Windows wrapper layout invalidation.
src/CommunityToolkit.Maui/Views/Expander/Expander.shared.cs Safer header/content replacement (casts/removes only when old value is an IView).
src/CommunityToolkit.Maui/Views/AvatarView.shared.cs Replaces internal element-backed bindables/interfaces with toolkit-defined bindable properties.
src/CommunityToolkit.Maui/Primitives/BindablePropertySourceGeneratorPrimitives/AttachedBindablePropertyAttribute.shared.cs Doc comment updated to avoid referencing a long API signature.
src/CommunityToolkit.Maui/Layouts/StateContainer/StateContainer.shared.cs Replaces internal helper usage in animation sequencing logic.
src/CommunityToolkit.Maui/ImageSources/GravatarImageSource.shared.cs Removes reliance on MAUI-internal cancellation token source; adds local CTS coordination.
src/CommunityToolkit.Maui/Extensions/HttpClientExtensions.shared.cs Replaces MAUI-internal StreamWrapper usage with HttpClient + response-owned stream wrapper.
src/CommunityToolkit.Maui/Extensions/DispatcherExtensions.shared.cs Adds toolkit-owned dispatcher helpers to replace internal dispatcher extensions.
src/CommunityToolkit.Maui/Extensions/AppThemeResourceExtension.shared.cs Replaces internal resources provider/source APIs; adds target-property-aware binding selection.
src/CommunityToolkit.Maui/Extensions/AppThemeObjectExtensions.shared.cs Uses target-property-aware AppTheme binding to preserve dynamic resources where possible.
src/CommunityToolkit.Maui/Essentials/AppTheme/AppThemeObject.shared.cs Reimplements AppTheme binding using public Binding/MultiBinding + converter logic.
src/CommunityToolkit.Maui/Behaviors/UserStoppedTypingBehavior.shared.cs Switches to toolkit dispatcher helper instead of internal dispatcher usage.
src/CommunityToolkit.Maui/Behaviors/PlatformBehaviors/Touch/GestureManager.shared.cs Removes internal ImageElement usage; updates dispatch + animation cancellation handling.
src/CommunityToolkit.Maui/Behaviors/PlatformBehaviors/ImageTouch/ImageTouchBehavior.shared.cs Updates source switching logic to avoid internal image element bindables.
src/CommunityToolkit.Maui/Behaviors/PlatformBehaviors/IconTintColor/IconTintColorBehavior.windows.cs Replaces internal image element source access with public Image/ImageButton source handling.
src/CommunityToolkit.Maui/Behaviors/PlatformBehaviors/IconTintColor/IconTintColorBehavior.macios.cs Avoids internal IImageElement by pattern-matching on Image/ImageButton.
src/CommunityToolkit.Maui/Behaviors/EventToCommandBehavior.shared.cs Replaces internal [Preserve] usage with trimming-friendly [DynamicDependency].
src/CommunityToolkit.Maui/Animations/FadeAnimation.shared.cs Adds suppression around non-cancellation-aware MAUI animation APIs (public surface only).
src/CommunityToolkit.Maui/Alerts/Snackbar/Snackbar.windows.cs Updates usings to align with toolkit-owned extensions.
src/CommunityToolkit.Maui/Alerts/Snackbar/Snackbar.shared.cs Replaces internal MAUI weak-reference helper usage with toolkit-owned equivalent.
src/CommunityToolkit.Maui.UnitTests/Views/AvatarView/AvatarViewInterfaceTests.cs Removes tests that depended on internal MAUI interfaces.
src/CommunityToolkit.Maui.UnitTests/Mocks/MockResourcesProvider.cs Removes internals-based mock used for system resources provider registration.
src/CommunityToolkit.Maui.UnitTests/Mocks/MockApplication.cs Removes dependency service registration that required MAUI internals.
src/CommunityToolkit.Maui.UnitTests/Essentials/AppThemeTests.cs Adds coverage for AppTheme dynamic-resource preservation behavior.
src/CommunityToolkit.Maui.MediaElement/Views/MauiMediaElement.macios.cs Removes reflection/internal handler usage; finds parent UIViewController via responder chain.
src/CommunityToolkit.Maui.MediaElement/Extensions/PageExtensions.shared.cs Uses public navigation/shell APIs to find the current page.
src/CommunityToolkit.Maui.Core/Views/SemanticOrderView/MauiSemanticOrderView.windows.cs Removes dependency on platform handler interface for TabIndex ordering.
src/CommunityToolkit.Maui.Core/Views/SemanticOrderView/MauiSemanticOrderView.tizen.cs Updates comment after removing internal handler dependency.
src/CommunityToolkit.Maui.Core/Views/SemanticOrderView/MauiSemanticOrderView.macios.cs Removes dependency on platform handler interface for accessibility ordering.
src/CommunityToolkit.Maui.Core/Views/SemanticOrderView/MauiSemanticOrderView.android.cs Removes dependency on platform handler interface for view ordering.
src/CommunityToolkit.Maui.Core/Platform/KeyboardExtensions/KeyboardExtensions.shared.cs Removes platform-handler-interface dependency; relies on public IViewHandler.

Comment thread src/CommunityToolkit.Maui/Layouts/StateContainer/StateContainer.shared.cs Outdated
Comment thread src/CommunityToolkit.Maui/Layouts/StateContainer/StateContainer.shared.cs Outdated
Comment thread src/CommunityToolkit.Maui/Extensions/HttpClientExtensions.shared.cs Outdated
Comment thread src/CommunityToolkit.Maui/Views/AvatarView.shared.cs Outdated
@jfversluis

Copy link
Copy Markdown
Member Author

Pushed follow-up commit 9cda65b3 addressing the review findings:

  • StateContainer now waits on one completion task per child animation instead of sharing a single TaskCompletionSource.
  • HttpClientExtensions.DownloadStreamAsync now disposes the HttpResponseMessage on failure paths, including if ReadAsStreamAsync throws.
  • GestureManager now uses TotalMilliseconds for translation/rotation-Y animation durations.
  • ImageTouchBehavior is restricted to supported image controls (Image/ImageButton) and has explicit ImageButton coverage.
  • AvatarView.FontSize now defaults to -1d to match MAUI font-size semantics.
  • MauiMediaElement keeps the public-API path and falls back to the current view controller when the page platform view responder chain does not yield one.

For James's #3222: I did not pull/cherry-pick that PR into this one because it is a broader MediaElement behavior fix with handler/test/playback-control changes beyond the IVT cleanup. This PR keeps the scoped fallback needed for the review comment. If #3222 lands first we can rebase this PR and drop/resolve the small overlap; if this PR lands first, #3222 can rebase on top.

Focused local validation after the commit:

  • CommunityToolkit.Maui builds for net10.0, net10.0-android, and net10.0-maccatalyst.
  • CommunityToolkit.Maui builds for net10.0 against dotnet/maui PR #34070 packages.
  • Focused tests passed: StateContainerTests, ImageTouchBehaviorTests, TouchBehaviorTests, AvatarViewInterfaceTests, AvatarViewTests (130 passed).
  • The MAUI-internals/[.NET 11] Migrate off internal MAUI APIs before InternalsVisibleTo removal #3097 scan remains clean.

@jfversluis
jfversluis force-pushed the jfversluis-toolkit-internals-audit branch from 25faf1e to 7e83015 Compare June 30, 2026 07:37
@jfversluis
jfversluis force-pushed the jfversluis-toolkit-internals-audit branch from 7f7b1a8 to a16ebcb Compare July 16, 2026 19:15
@TheCodeTraveler
TheCodeTraveler requested a review from Copilot July 16, 2026 19:18
Comment thread .github/workflows/dotnet-build.yml Outdated
jfversluis and others added 12 commits July 16, 2026 21:20
Remove CommunityToolkit.Maui dependencies on MAUI internal APIs and implementation details so MAUI can remove InternalsVisibleTo for the toolkit without breaking supported package builds.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace MAUI internal RequireFontManager calls with public MauiContext service resolution.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fix review findings from the MAUI internals cleanup pass: wait for each StateContainer child animation independently, dispose failed HTTP responses, use full animation durations, restrict ImageTouch to supported image controls, preserve the MediaElement view-controller fallback, and align AvatarView default font size with MAUI semantics.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jfversluis
jfversluis force-pushed the jfversluis-toolkit-internals-audit branch from 35a2b2b to 5ebeab6 Compare July 16, 2026 19:21

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

Copilot reviewed 44 out of 44 changed files in this pull request and generated 2 comments.

Comment thread src/CommunityToolkit.Maui/Extensions/DispatcherExtensions.shared.cs
Comment thread src/CommunityToolkit.Maui/Extensions/HttpClientExtensions.shared.cs
@jfversluis
jfversluis force-pushed the jfversluis-toolkit-internals-audit branch from 7c70bc6 to 6919f8b Compare July 16, 2026 19:55
jfversluis and others added 2 commits July 16, 2026 21:55
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

@TheCodeTraveler TheCodeTraveler 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.

Thanks Gerald!

Just FYI - I had planned on doing this work alongside our release supporting .NET 11 in November. I can review this PR and mark it as approved, however we'll wait to merge it alongside the Add .NET 11 Support PR I'll be creating in a few months. I'll keep an eye on it to ensure there's no merge conflicts from future PRs.

For this PR, just assume that it is only targeting .NET 11.

Please also remove all of the backwards compatibility to .NET 10, eg #if NET11_0_OR_GREATER. We won't be supporting .NET 10 once we migrate to .NET 11.

It's ok if this PR has failing builds for now because it's targeting .NET 11. I'll fix all that stuff when I do the work to migrate to .NET 11.

Comment thread src/CommunityToolkit.Maui/Alerts/Snackbar/Snackbar.shared.cs Outdated
Comment thread src/CommunityToolkit.Maui/Extensions/DispatcherExtensions.shared.cs
Comment thread src/CommunityToolkit.Maui/Animations/FadeAnimation.shared.cs Outdated
Comment thread src/CommunityToolkit.Maui/Extensions/DispatcherExtensions.shared.cs Outdated
Comment thread src/CommunityToolkit.Maui/Views/Expander/Expander.windows.cs Outdated
Comment thread src/CommunityToolkit.Maui/Views/AvatarView.shared.cs
jfversluis and others added 2 commits July 16, 2026 22:54
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Build the source generator benchmark project serially and run it with --no-build to avoid CI file-lock races in shared source-generator outputs.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jfversluis

Copy link
Copy Markdown
Member Author

@TheCodeTraveler This has been rebased onto the latest main and validated. Could we please prioritize reviewing and merging this sooner rather than later? We expect to merge the corresponding .NET MAUI 11 change that removes the Toolkit InternalsVisibleTo access soon, so landing this first will help ensure Toolkit users can move to .NET MAUI 11 from day one without regressions.

Use the .NET 11 cancellation-aware MAUI animation overloads directly and remove the conditional/net10 WaitAsync fallback paths from the internals-removal work.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jfversluis

jfversluis commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

@TheCodeTraveler Updated per the .NET 11-only direction in d2ca998b: removed the NET11_0_OR_GREATER sample animation guards and switched the Toolkit animation paths called out in review to the .NET 11 cancellation-aware MAUI overloads directly. I also re-checked the two Copilot comments from the latest review; the dispatcher false-return handling and ResponseStream async delegation are already addressed on this branch. Added-line private/reflection/internal API scan remains clean. Local net10 build now fails as expected on the new MAUI 11 overloads, and net11 validation is blocked in this worktree by the installed SDK only supporting up to .NET 10.

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

Successfully merging this pull request may close these issues.

[.NET 11] Migrate off internal MAUI APIs before InternalsVisibleTo removal

4 participants